// --------------------------------------------------------------------------------------
// Charting API for F# (version 0.60)
// --------------------------------------------------------------------------------------

#nowarn "40"
#if INTERACTIVE
#r "System.Windows.Forms.DataVisualization.dll"
#endif

namespace MSDN.FSharp.Charting

open System
open System.Collections
open System.Collections.Generic
open System.Drawing
open System.Reflection
open System.Runtime.InteropServices
open System.Windows.Forms
open System.Windows.Forms.DataVisualization
open System.Windows.Forms.DataVisualization.Charting

// ----------------------------------- 
// Charting.ClipboardMetafileHelper.fs
// ----------------------------------- 
module internal ClipboardMetafileHelper =
    [<DllImport("user32.dll")>]
    extern bool OpenClipboard(nativeint hWndNewOwner)
    [<DllImport("user32.dll")>]
    extern bool EmptyClipboard()
    [<DllImport("user32.dll")>]
    extern IntPtr SetClipboardData(uint32 uFormat, nativeint hMem)
    [<DllImport("user32.dll")>]
    extern bool CloseClipboard()
    [<DllImport("gdi32.dll")>]
    extern nativeint CopyEnhMetaFile(nativeint hemfSrc, nativeint hNULL)
    [<DllImport("gdi32.dll")>]
    extern bool DeleteEnhMetaFile(IntPtr hemf)
    
    // Metafile mf is set to a state that is not valid inside this function.
    let PutEnhMetafileOnClipboard(hWnd, mf : System.Drawing.Imaging.Metafile) =
        let mutable bResult = false
        let hEMF = mf.GetHenhmetafile() // invalidates mf
        if (hEMF <> 0n) then
            let hEMF2 = CopyEnhMetaFile(hEMF, 0n)
            if (hEMF2 <> 0n) then
                if OpenClipboard(hWnd) && EmptyClipboard() then
                    let hRes = SetClipboardData( 14u (*CF_ENHMETAFILE*), hEMF2 );
                    bResult <- hRes = hEMF2
                    CloseClipboard() |> ignore
            DeleteEnhMetaFile( hEMF ) |> ignore
        bResult

// ----------------------------------- 
// Charting.ChartStyles.fs
// ----------------------------------- 
module ChartStyles =

    // --------------------------------------------------------------------------------------
    // [AUTOGENERATED]: Enumerations for custom attribute types

    /// Specifies the plot area shape in Radar and Polar charts.
    type AreaDrawingStyle = 
        | Circle = 0
        | Polygon = 1

    /// Specifies the placement of the data point label.
    type BarLabelStyle = 
        | Outside = 0
        | Left = 1
        | Right = 2
        | Center = 3

    /// Specifies the text orientation of the axis labels in Radar
    /// and Polar charts.
    type CircularLabelStyle = 
        | Circular = 0
        | Horizontal = 1
        | Radial = 2

    /// Specifies the drawing style of data points.
    type DrawingStyle = 
        | Cylinder = 0
        | Emboss = 1
        | LightToDark = 2
        | Wedge = 3
        | Default = 4

    /// Specifies whether series of the same chart type are drawn
    /// next to each other instead of overlapping each other.
    type DrawSideBySide = 
        | Auto = 0
        | True = 1
        | False = 2

    /// Specifies the value to be used for empty points.
    type EmptyPointValue = 
        | Average = 0
        | Zero = 1

    /// Specifies the appearance of the marker at the center value
    /// of the error bar.
    type ErrorBarCenterMarkerStyle = 
        | None = 0
        | Line = 1
        | Square = 2
        | Circle = 3
        | Diamond = 4
        | Triangle = 5
        | Cross = 6
        | Star4 = 7
        | Star5 = 8
        | Star6 = 9
        | Star10 = 10

    /// Specifies the visibility of the upper and lower error values.
    type ErrorBarStyle = 
        | Both = 0
        | UpperError = 1
        | LowerError = 2

    /// Specifies how the upper and lower error values are calculated
    /// for the center values of the ErrorBarSeries.
    type ErrorBarType = 
        | FixedValue = 0
        | Percentage = 1
        | StandardDeviation = 2
        | StandardError = 3

    /// Specifies the 3D drawing style of the Funnel chart type.
    type Funnel3DDrawingStyle = 
        | CircularBase = 0
        | SquareBase = 1

    /// Specifies the data point label placement of the Funnel chart
    /// type when the FunnelLabelStyle is set to Inside.
    type FunnelInsideLabelAlignment = 
        | Center = 0
        | Top = 1
        | Bottom = 2

    /// Specifies the data point label style of the Funnel chart type.
    type FunnelLabelStyle = 
        | Inside = 0
        | Outside = 1
        | OutsideInColumn = 2
        | Disabled = 3

    /// Placement of the data point label in the Funnel chart
    /// when FunnelLabelStyle is set to Outside or OutsideInColumn.
    type FunnelOutsideLabelPlacement = 
        | Right = 0
        | Left = 1

    /// Specifies the style of the Funnel chart type.
    type FunnelStyle = 
        | YIsWidth = 0
        | YIsHeight = 1

    /// Specifies the label position of the data point.
    type LabelStyle = 
        | Auto = 0
        | Top = 1
        | Bottom = 2
        | Right = 3
        | Left = 4
        | TopLeft = 5
        | TopRight = 6
        | BottomLeft = 7
        | BottomRight = 8
        | Center = 9

    /// Specifies the Y value to use as the data point
    /// label.
    type LabelValueType = 
        | High = 0
        | Low = 1
        | Open = 2
        | Close = 3

    /// Specifies the marker style for open and close values.
    type OpenCloseStyle = 
        | Triangle = 0
        | Line = 1
        | Candlestick = 2

    /// Specifies the drawing style of the data points.
    type PieDrawingStyle = 
        | Default = 0
        | SoftEdge = 1
        | Concave = 2

    /// Specifies the label style of the data points.
    type PieLabelStyle = 
        | Disabled = 0
        | Inside = 1
        | Outside = 2

    /// Specifies the drawing style of the Polar chart type.
    type PolarDrawingStyle = 
        | Line = 0
        | Marker = 1

    /// Specifies the 3D drawing style of the Pyramid chart type.
    type Pyramid3DDrawingStyle = 
        | CircularBase = 0
        | SquareBase = 1

    /// Specifies the placement of the data point labels in the
    /// Pyramid chart when they are placed inside the pyramid.
    type PyramidInsideLabelAlignment = 
        | Center = 0
        | Top = 1
        | Bottom = 2

    /// Specifies the style of data point labels in the Pyramid chart.
    type PyramidLabelStyle = 
        | Inside = 0
        | Outside = 1
        | OutsideInColumn = 2
        | Disabled = 3

    /// Specifies the placement of the data point labels in the
    /// Pyramid chart when the labels are placed outside the pyramid.
    type PyramidOutsideLabelPlacement = 
        | Right = 0
        | Left = 1

    /// Specifies whether the data point value represents a linear height
    /// or the surface of the segment.
    type PyramidValueType = 
        | Linear = 0
        | Surface = 1

    /// Specifies the drawing style of the Radar chart.
    type RadarDrawingStyle = 
        | Area = 0
        | Line = 1
        | Marker = 2

    /// Specifies whether markers for open and close prices are displayed.
    type ShowOpenClose = 
        | Both = 0
        | Open = 1
        | Close = 2

    // [/AUTOGENERATED]
    // --------------------------------------------------------------------------------------


    // Background helpers
    [<RequireQualifiedAccess>]
    type Background = 
        | EmptyColor
        | Gradient of Color * Color * Charting.GradientStyle
        | Solid of Color

    let inline applyBackground (obj:^T) back =
        match back with 
        | Background.EmptyColor ->
            (^T : (member set_BackColor : Color -> unit) (obj, Color.Empty))
        | Background.Solid color ->
            (^T : (member set_BackColor : Color -> unit) (obj, color))
        | Background.Gradient(first, second, style) ->
            (^T : (member set_BackColor : Color -> unit) (obj, first))
            (^T : (member set_BackSecondaryColor : Color -> unit) (obj, second))
            (^T : (member set_BackGradientStyle : Charting.GradientStyle -> unit) (obj, style))

    // Default font used when creating styles, titles, and legends
    let DefaultFont = 
        new Font("Calibri", 9.0f, FontStyle.Regular)

    // Type used for defining defaults
    type internal ChartStyleDefault =
        { ChartType:Charting.SeriesChartType option; ParentType:Type option; PropertyName:string; PropertyDefault:obj }

    // Definition of defaults for the chart
    let internal PropertyDefaults = 
        [ // Define type specific defaults
          { ChartStyleDefault.ChartType = None; ParentType = Some(typeof<Charting.LabelStyle>); PropertyName="Font"; PropertyDefault=(box (new Font("Arial Narrow", 10.0f, FontStyle.Regular))) }
          { ChartStyleDefault.ChartType = Some(Charting.SeriesChartType.Line); ParentType = Some(typeof<Charting.Series>); PropertyName="BorderWidth"; PropertyDefault=(box 2) }
          // Define series ToolTip defaults
          { ChartStyleDefault.ChartType = Some(Charting.SeriesChartType.Line); ParentType = Some(typeof<Charting.Series>); PropertyName="ToolTip"; PropertyDefault=(box "X=#VALX, Y=#VAL") }
          { ChartStyleDefault.ChartType = Some(Charting.SeriesChartType.Spline); ParentType = Some(typeof<Charting.Series>); PropertyName="ToolTip"; PropertyDefault=(box "X=#VALX, Y=#VAL") }
          { ChartStyleDefault.ChartType = Some(Charting.SeriesChartType.Bar); ParentType = Some(typeof<Charting.Series>); PropertyName="ToolTip"; PropertyDefault=(box "X=#VALX, Y=#VAL") }
          { ChartStyleDefault.ChartType = Some(Charting.SeriesChartType.Column); ParentType = Some(typeof<Charting.Series>); PropertyName="ToolTip"; PropertyDefault=(box "X=#VALX, Y=#VAL") }
          { ChartStyleDefault.ChartType = Some(Charting.SeriesChartType.Area); ParentType = Some(typeof<Charting.Series>); PropertyName="ToolTip"; PropertyDefault=(box "X=#VALX, Y=#VAL") }
          { ChartStyleDefault.ChartType = Some(Charting.SeriesChartType.StackedBar); ParentType = Some(typeof<Charting.Series>); PropertyName="ToolTip"; PropertyDefault=(box "X=#VALX, Y=#VAL") }
          { ChartStyleDefault.ChartType = Some(Charting.SeriesChartType.StackedColumn); ParentType = Some(typeof<Charting.Series>); PropertyName="ToolTip"; PropertyDefault=(box "X=#VALX, Y=#VAL") }
          { ChartStyleDefault.ChartType = Some(Charting.SeriesChartType.StackedArea); ParentType = Some(typeof<Charting.Series>); PropertyName="ToolTip"; PropertyDefault=(box "X=#VALX, Y=#VAL") }
          { ChartStyleDefault.ChartType = Some(Charting.SeriesChartType.StackedBar100); ParentType = Some(typeof<Charting.Series>); PropertyName="ToolTip"; PropertyDefault=(box "X=#VALX, Y=#VAL") }
          { ChartStyleDefault.ChartType = Some(Charting.SeriesChartType.StackedColumn100); ParentType = Some(typeof<Charting.Series>); PropertyName="ToolTip"; PropertyDefault=(box "X=#VALX, Y=#VAL") }
          { ChartStyleDefault.ChartType = Some(Charting.SeriesChartType.StackedArea100); ParentType = Some(typeof<Charting.Series>); PropertyName="ToolTip"; PropertyDefault=(box "X=#VALX, Y=#VAL") }
          { ChartStyleDefault.ChartType = Some(Charting.SeriesChartType.SplineArea); ParentType = Some(typeof<Charting.Series>); PropertyName="ToolTip"; PropertyDefault=(box "X=#VALX, Y=#VAL") }
          { ChartStyleDefault.ChartType = Some(Charting.SeriesChartType.Range); ParentType = Some(typeof<Charting.Series>); PropertyName="ToolTip"; PropertyDefault=(box "X=#VALX, High=#VALY1, Low=#VALY2") }
          { ChartStyleDefault.ChartType = Some(Charting.SeriesChartType.RangeBar); ParentType = Some(typeof<Charting.Series>); PropertyName="ToolTip"; PropertyDefault=(box "Y=#VALX, High=#VALY1, Low=#VALY2") }
          { ChartStyleDefault.ChartType = Some(Charting.SeriesChartType.RangeColumn); ParentType = Some(typeof<Charting.Series>); PropertyName="ToolTip"; PropertyDefault=(box "X=#VALX, High=#VALY1, Low=#VALY2") }
          { ChartStyleDefault.ChartType = Some(Charting.SeriesChartType.SplineRange); ParentType = Some(typeof<Charting.Series>); PropertyName="ToolTip"; PropertyDefault=(box "X=#VALX, High=#VALY1, Low=#VALY2") }
          { ChartStyleDefault.ChartType = Some(Charting.SeriesChartType.Point); ParentType = Some(typeof<Charting.Series>); PropertyName="ToolTip"; PropertyDefault=(box "X=#VALX, Y=#VAL") }
          { ChartStyleDefault.ChartType = Some(Charting.SeriesChartType.PointAndFigure); ParentType = Some(typeof<Charting.Series>); PropertyName="ToolTip"; PropertyDefault=(box "X=#VALX, High=#VALY1, Low=#VALY2") }
          { ChartStyleDefault.ChartType = Some(Charting.SeriesChartType.ThreeLineBreak); ParentType = Some(typeof<Charting.Series>); PropertyName="ToolTip"; PropertyDefault=(box "X=#VALX, Y=#VAL") }
          { ChartStyleDefault.ChartType = Some(Charting.SeriesChartType.StepLine); ParentType = Some(typeof<Charting.Series>); PropertyName="ToolTip"; PropertyDefault=(box "X=#VALX, Y=#VAL") }
          { ChartStyleDefault.ChartType = Some(Charting.SeriesChartType.Pie); ParentType = Some(typeof<Charting.Series>); PropertyName="ToolTip"; PropertyDefault=(box "#VAL") }
          { ChartStyleDefault.ChartType = Some(Charting.SeriesChartType.Doughnut); ParentType = Some(typeof<Charting.Series>); PropertyName="ToolTip"; PropertyDefault=(box "#VAL") }
          { ChartStyleDefault.ChartType = Some(Charting.SeriesChartType.BoxPlot); ParentType = Some(typeof<Charting.Series>); PropertyName="ToolTip"; PropertyDefault=(box "Lower Whisker=#VALY1, Upper Whisker=#VALY2, Lower Box=#VALY3, Upper Box=#VALY4") }
          { ChartStyleDefault.ChartType = Some(Charting.SeriesChartType.Candlestick); ParentType = Some(typeof<Charting.Series>); PropertyName="ToolTip"; PropertyDefault=(box "High=#VALY1, Low=#VALY2, Open=#VALY3, Close=#VALY4") }
          { ChartStyleDefault.ChartType = Some(Charting.SeriesChartType.Stock); ParentType = Some(typeof<Charting.Series>); PropertyName="ToolTip"; PropertyDefault=(box "High=#VALY1, Low=#VALY2, Open=#VALY3, Close=#VALY4") }
          { ChartStyleDefault.ChartType = Some(Charting.SeriesChartType.Renko); ParentType = Some(typeof<Charting.Series>); PropertyName="ToolTip"; PropertyDefault=(box "X=#VALX, Y=#VAL") }
          { ChartStyleDefault.ChartType = Some(Charting.SeriesChartType.Bubble); ParentType = Some(typeof<Charting.Series>); PropertyName="ToolTip"; PropertyDefault=(box "X=#VALX, Y=#VALY1, Size=#VALY2") }
          { ChartStyleDefault.ChartType = Some(Charting.SeriesChartType.ErrorBar); ParentType = Some(typeof<Charting.Series>); PropertyName="ToolTip"; PropertyDefault=(box "X=#VALX, Y=#VALY1, Lower=#VALY2, Upper=#VALY3") }
          { ChartStyleDefault.ChartType = Some(Charting.SeriesChartType.Funnel); ParentType = Some(typeof<Charting.Series>); PropertyName="ToolTip"; PropertyDefault=(box "X=#VALX, Y=#VAL") }
          { ChartStyleDefault.ChartType = Some(Charting.SeriesChartType.Pyramid); ParentType = Some(typeof<Charting.Series>); PropertyName="ToolTip"; PropertyDefault=(box "X=#VALX, Y=#VAL") }
          { ChartStyleDefault.ChartType = Some(Charting.SeriesChartType.Kagi); ParentType = Some(typeof<Charting.Series>); PropertyName="ToolTip"; PropertyDefault=(box "X=#VALX, Y=#VAL") }
          { ChartStyleDefault.ChartType = Some(Charting.SeriesChartType.Polar); ParentType = Some(typeof<Charting.Series>); PropertyName="ToolTip"; PropertyDefault=(box "Angle=#VALX, Distance=#VAL") }
          { ChartStyleDefault.ChartType = Some(Charting.SeriesChartType.Radar); ParentType = Some(typeof<Charting.Series>); PropertyName="ToolTip"; PropertyDefault=(box "Point=#VALX, Distance=#VAL") }
          // Define global defaults
          { ChartStyleDefault.ChartType = None; ParentType = None; PropertyName="Font"; PropertyDefault=(box DefaultFont) } ]

// ----------------------------------- 
// Charting.ChartFormUtilities.fs
// ----------------------------------- 
open ChartStyles

module internal ChartFormUtilities = 

    let private typesToClone = 
        [ typeof<System.Windows.Forms.DataVisualization.Charting.LabelStyle>;
          typeof<System.Windows.Forms.DataVisualization.Charting.Axis>;
          typeof<System.Windows.Forms.DataVisualization.Charting.Grid>; 
          typeof<System.Windows.Forms.DataVisualization.Charting.TickMark>
          typeof<System.Windows.Forms.DataVisualization.Charting.ElementPosition>; 
          typeof<System.Windows.Forms.DataVisualization.Charting.AxisScaleView>; 
          typeof<System.Windows.Forms.DataVisualization.Charting.AxisScrollBar>; ]

    let private typesToCopy = [ typeof<Font>; typeof<String> ]

    let private applyDefaults (chartType:SeriesChartType) (target:'a) (targetType:Type) (property:PropertyInfo) = 
        let isMatch propDefault = 
            if String.Equals(propDefault.PropertyName, property.Name) then
                match (propDefault.ChartType, propDefault.ParentType) with
                | (Some seriesType, Some parentType) -> (targetType.IsAssignableFrom(parentType) || targetType.IsSubclassOf(parentType)) && chartType = seriesType
                | (Some seriesType, None) -> chartType = seriesType
                | (None, Some parentType) -> targetType.IsAssignableFrom(parentType) || targetType.IsSubclassOf(parentType)
                | (_, _) -> true
            else
                false
        match List.tryFind isMatch PropertyDefaults with
        | Some item -> property.SetValue(target, item.PropertyDefault, [||])
        | _ -> ()

    let applyPropertyDefaults (chartType:SeriesChartType) (target:'a) = 
        let visited = new System.Collections.Generic.Dictionary<_, _>()
        let rec loop target = 
            if not (visited.ContainsKey target) then
                visited.Add(target, true)
                let targetType = target.GetType()
                for property in targetType.GetProperties(BindingFlags.Public ||| BindingFlags.Instance) do
                    if property.CanRead then
                        if typesToClone |> Seq.exists ((=) property.PropertyType) then
                            loop (property.GetValue(target, [||]))
                        elif property.CanWrite then
                            if property.PropertyType.IsValueType || typesToCopy |> Seq.exists ((=) property.PropertyType) then
                                applyDefaults chartType target targetType property
        loop target

    let applyProperties (target:'a) (source:'a) = 
        let visited = new System.Collections.Generic.Dictionary<_, _>()
        let rec loop target source = 
            if not (visited.ContainsKey target) then
                visited.Add(target, true)
                let ty = target.GetType()
                for p in ty.GetProperties(BindingFlags.Public ||| BindingFlags.Instance) do
                    if p.CanRead then
                        if typesToClone |> Seq.exists ((=) p.PropertyType) then
                            loop (p.GetValue(target, [||])) (p.GetValue(source, [||]))
                        elif p.CanWrite then
                            if p.PropertyType.IsValueType || typesToCopy |> Seq.exists ((=) p.PropertyType) then
                                if p.GetSetMethod().GetParameters().Length <= 1 then
                                    p.SetValue(target, p.GetValue(source, [||]), [||])
//                                else
//                                    printfn "Indexed property %s.%s (type %s)" ty.Name p.Name p.PropertyType.Name
//                            else
//                                printfn "Not sure what to do with %s.%s (type %s)" ty.Name p.Name p.PropertyType.Name
//                        else 
//                            printfn "Cannot write %s.%s" ty.Name p.Name    
        loop target source

    let createCounter() = 
        let count = ref 0
        (fun () -> incr count; !count) 

// ----------------------------------- 
// Charting.ChartData.fs
// ----------------------------------- 
open ChartFormUtilities
open ChartStyles

module ChartData = 

    module internal Internal = 
        [<RequireQualifiedAccess>]
        type internal ChartData =
            // single value
            | YValues of IEnumerable
            | XYValues of IEnumerable * IEnumerable
            | YValuesChanging of int * IObservable<float>
            | XYValuesChanging of int * IObservable<IConvertible * float>
            // multiple values
            | MultiYValues of IEnumerable[]
            | MultiYValuesChanging of int * IObservable<float[]>
            | XMultiYValues of IEnumerable * IEnumerable[]    
            | XMultiYValuesChanging of int * IObservable<IConvertible * float[]>

            // stacked values
            | StackedYValues of seq<IEnumerable>
            | StackedXYValues of seq<IEnumerable * IEnumerable>

            // This one is treated specially (for box plot, we need to add data as a separate series)
            // TODO: This is a bit inconsistent - we should unify the next one with the last 
            // four and then handle boxplot chart type when adding data to the series
            | BoxPlotYArrays of seq<IEnumerable>
            | BoxPlotXYArrays of seq<IConvertible * IEnumerable>
            // A version of BoxPlot arrays with X values is missing (could be useful)
            // Observable version is not supported (probably nobody needs it)
            // (Unifying would sovlve these though)

        // ----------------------------------------------------------------------------------
        // Utilities for working with enumerable and tuples

        let map f (source:seq<_>) = 
          { new IEnumerable with
              member x.GetEnumerator() = 
                let en = source.GetEnumerator()
                { new IEnumerator with 
                    member x.Current = box (f en.Current)
                    member x.MoveNext() = en.MoveNext()
                    member x.Reset() = en.Reset() } }

        // There are quite a few variations - let's have some write-only combinator fun

        let useq (e:seq<_>) = e :> IEnumerable

        let el1of3 (a, _, _) = a 
        let el2of3 (_, a, _) = a 
        let el3of3 (_, _, a) = a 

        let el1of4 (a, _, _, _) = a 
        let el2of4 (_, a, _, _) = a 
        let el3of4 (_, _, a, _) = a 
        let el4of4 (_, _, _, a) = a 

        let el1of5 (a, _, _, _, _) = a 
        let el2of5 (_, a, _, _, _) = a 
        let el3of5 (_, _, a, _, _) = a 
        let el4of5 (_, _, _, a, _) = a 
        let el5of5 (_, _, _, _, a) = a 

        let el1of6 (a, _, _, _, _, _) = a 
        let el2of6 (_, a, _, _, _, _) = a 
        let el3of6 (_, _, a, _, _, _) = a 
        let el4of6 (_, _, _, a, _, _) = a 
        let el5of6 (_, _, _, _, a, _) = a 
        let el6of6 (_, _, _, _, _, a) = a 

        let tuple2 f g (x, y) = f x, g y
        let tuple3 f g h (x, y, z) = f x, g y, h z
        let tuple4 f g h i (x, y, z, w) = f x, g y, h z, i w

        let arr2 (a, b) = [| a; b |]
        let arr3 (a, b, c) = [| a; b; c |]
        let arr4 (a, b, c, d) = [| a; b; c; d |]

        // Converts Y value of a chart (defines the type too)
        let culture = System.Globalization.CultureInfo.InvariantCulture
        let cval (v:System.IConvertible) = v.ToDouble culture
        let cobj (v:System.IConvertible) = v

        // Alternative option:
        // (uses op_Explicit -> float constraint for values and any 'obj' allowed for X values)
        //   let cval a = float a' 
        //   let cobj (a:obj) = a

        // ----------------------------------------------------------------------------------
        // Single Y value

        // Y values only
        let oneY (source:seq<_>) = 
          ChartData.YValues(map cval source)
        // X and Y values as tuples
        let oneXYSeq (source:seq<_ * _>) = 
          ChartData.XYValues(map (fst >> cobj) source, map (snd >> cval >> box) source)
        // X and Y values as sequences
        let oneXY (xsource:seq<_>) (ysource:seq<_>) = 
          ChartData.XYValues(map cobj xsource, map cval ysource)
        
        // Y values changing
        let oneYObs maxPoints (source) = 
          ChartData.YValuesChanging(maxPoints, source |> Observable.map cval)
        // X and Y values as tuples, changing
        let oneXYObs maxPoints (source) = 
          ChartData.XYValuesChanging(maxPoints, source |> Observable.map (tuple2 cobj cval))

        // ----------------------------------------------------------------------------------
        // Two Y values

        // Y values only
        let twoY source = 
          ChartData.MultiYValues([| map (fst >> cval >> box) source; map (snd >> cval >> box) source |])
        // X and Y values as tuples
        let twoXYSeq source = 
          ChartData.XMultiYValues(map (fst >> cobj) source, [| map (snd >> fst >> cval >> box) source; map (snd >> snd >> cval >> box) source |])
        // X and Y values as sequences
        let twoXY xsource ysource1 ysource2 = 
          ChartData.XMultiYValues(map cobj xsource, [| map cval ysource1; map cval ysource2 |])

        // Y values changing
        let twoYObs maxPoints (source) = 
          ChartData.MultiYValuesChanging(maxPoints, source |> Observable.map (tuple2 cval cval >> arr2))
        // X and Y values as tuples, changing
        let twoXYObs maxPoints (source) = 
          ChartData.XMultiYValuesChanging(maxPoints, source |> Observable.map (tuple2 cobj (tuple2 cval cval >> arr2)))

        // ----------------------------------------------------------------------------------
        // Three Y values

        // Y values only
        let threeY source = 
          ChartData.MultiYValues([| map (el1of3 >> cval >> box) source; map (el2of3 >> cval >> box) source; map (el3of3 >> cval >> box) source |])
        // X and Y values as tuples
        let threeXYSeq source = 
          ChartData.XMultiYValues(map (fst >> cobj) source, [| map (snd >> el1of3 >> cval >> box) source; map (snd >> el2of3 >> cval >> box) source; map (snd >> el3of3 >> cval >> box) source |])
        // X and Y values as sequences
        let threeXY xsource ysource1 ysource2 ysource3 = 
          ChartData.XMultiYValues(map cobj xsource, [| map cval ysource1; map cval ysource2; map cval ysource3 |])

        // Y values changing
        let threeYObs maxPoints (source) = 
          ChartData.MultiYValuesChanging(maxPoints, source |> Observable.map (tuple3 cval cval cval >> arr3))
        // X and Y values as tuples, changing
        let threeXYObs maxPoints (source) = 
          ChartData.XMultiYValuesChanging(maxPoints, source |> Observable.map (tuple2 cobj (tuple3 cval cval cval >> arr3)))

        // ----------------------------------------------------------------------------------
        // Four Y values

        // Y values only
        let fourY source = 
          ChartData.MultiYValues([| map (el1of4 >> cval >> box) source; map (el2of4 >> cval >> box) source; map (el3of4 >> cval >> box) source; map (el4of4 >> cval >> box) source |])
        // X and Y values as tuples
        let fourXYSeq source = 
          ChartData.XMultiYValues(map (fst >> cobj) source, [| map (snd >> el1of4 >> cval >> box) source; map (snd >> el2of4 >> cval >> box) source; map (snd >> el3of4 >> cval >> box) source; map (snd >> el4of4 >> cval >> box) source |])
        // X and Y values as sequences
        let fourXY xsource ysource1 ysource2 ysource3 ysource4 = 
          ChartData.XMultiYValues(map cobj xsource, [| map cval ysource1; map cval ysource2; map cval ysource3; map cval ysource4 |])

        // Y values changing
        let fourYObs maxPoints (source) = 
          ChartData.MultiYValuesChanging(maxPoints, source |> Observable.map (tuple4 cval cval cval cval >> arr4))
        // X and Y values as tuples, changing
        let fourXYObs maxPoints (source) = 
          ChartData.XMultiYValuesChanging(maxPoints, source |> Observable.map (tuple2 cobj (tuple4 cval cval cval cval >> arr4)))

        // ----------------------------------------------------------------------------------
        // Six or more values

        // Y values only
        let sixY source = 
          ChartData.MultiYValues([| map (el1of6 >> cval >> box) source; map (el2of6 >> cval >> box) source; map (el3of6 >> cval >> box) source; map (el4of6 >> cval >> box) source; map (el5of6 >> cval >> box) source; map (el6of6 >> cval >> box) source |])
        // X and Y values as array
        let sixXYArr source = 
          let length = source |> Seq.head |> snd |> Array.length
          ChartData.XMultiYValues(map (fst >> cobj) source, [| for i in 0 .. length-1 -> seq { for (_, v) in source -> cval v.[i] } |> useq |])
        // Y values (for BoxPlot charts)
        let sixYArrBox (source:seq<#IConvertible[]>) = 
          ChartData.BoxPlotYArrays (source |> Seq.map (map cval))
        // X and Y values as array (for BoxPlot charts)
        let sixXYArrBox source = 
          let series = (source |> Seq.map (fun item -> cobj (fst item), map cval (snd item)))
          ChartData.BoxPlotXYArrays(series)

        // ----------------------------------------------------------------------------------
        // Stacked sequence values

        // Sequence of Y Values only
        let seqY (source:list<list<'TY>>) = 
            ChartData.StackedYValues (source |> List.map (map cval))
        // Sequence of X and Y Values only
        let seqXY (source: list<list<'TX * 'TY>>) = 
            let series = (source |> List.map (fun item -> List.unzip item |> (fun itemXY -> (map cobj (fst itemXY), map cval (snd itemXY))) ))
            ChartData.StackedXYValues (series)

        // --------------------------------------------------------------------------------------

        let internal bindObservable (chart:Chart) (series:Series) maxPoints values adder = 
            series.Points.Clear()
            let rec disp = 
                values |> Observable.subscribe (fun v ->
                    let op () = 
                        try
                            adder series.Points v
                            if maxPoints <> -1 && series.Points.Count > maxPoints then
                                series.Points.RemoveAt(0) 
                        with 
                        | :? NullReferenceException ->
                            disp.Dispose() 
                    if chart.InvokeRequired then
                        chart.Invoke(Action(op)) |> ignore
                    else 
                        op())
            ()


        let internal setSeriesData resetSeries (series:Series) data (chart:Chart) setCustomProperty =             

            let bindBoxPlot values getSeries getLabel (displayLabel:bool) = 
                let labels = chart.ChartAreas.[0].AxisX.CustomLabels
                let name = series.Name
                if resetSeries then
                    labels.Clear()
                    while chart.Series.Count > 1 do chart.Series.RemoveAt(1)                                 
                let seriesNames = 
                    values |> Seq.mapi (fun index series ->
                        let name = getLabel name index series
                        let dataSeries = new Series(name, Enabled = false, ChartType=SeriesChartType.BoxPlot)
                        dataSeries.Points.DataBindY [| getSeries series |]
                        if displayLabel then
                            labels.Add(float (index), float (index + 2), name) |> ignore
                            dataSeries.AxisLabel <- name
                            dataSeries.Label <- name
                        chart.Series.Add dataSeries
                        name )
                let boxPlotSeries = seriesNames |> String.concat ";"
                setCustomProperty("BoxPlotSeries", boxPlotSeries)

            let bindStackedChart values binder =                
                let name = series.Name
                let chartType = series.ChartType       
                while chart.Series.Count > 0 do chart.Series.RemoveAt(0)        
                values |> Seq.iteri (fun index seriesValue ->
                    let name = sprintf "Stacked_%s_%d" name index
                    let dataSeries = new Series(name, Enabled = false, ChartType=chartType)
                    applyProperties dataSeries series
                    dataSeries.Name <- name
                    binder dataSeries seriesValue
                    chart.Series.Add dataSeries)

            match data with 
            // Single Y value 
            | ChartData.YValues ys ->
                series.Points.DataBindY [| ys |]
            | ChartData.XYValues(xs, ys) ->
                series.Points.DataBindXY(xs, [| ys |])
            | ChartData.XYValuesChanging(maxPoints, xys) ->
                bindObservable chart series maxPoints xys (fun pts (x, y) -> pts.AddXY(x, y) |> ignore)
            | ChartData.YValuesChanging(maxPoints, ys) ->
                bindObservable chart series maxPoints ys (fun pts y -> pts.AddY(y) |> ignore)
            
            // Multiple Y values
            // TODO: Won't work for BoxPlot chart when the array contains more than 6 values
            // (but on the other hand, this will work for all 2/3/4 Y values charts)
            | ChartData.XMultiYValues(xs, yss) -> 
                series.Points.DataBindXY(xs, yss)
            | ChartData.MultiYValues yss ->
                series.Points.DataBindY yss
            | ChartData.MultiYValuesChanging(maxPoints, yss) ->
                bindObservable chart series maxPoints yss (fun pts ys -> pts.AddY(Array.map box ys) |> ignore)
            | ChartData.XMultiYValuesChanging(maxPoints, yss) ->
                bindObservable chart series maxPoints yss (fun pts (x, ys) -> pts.AddXY(x, Array.map box ys) |> ignore)
            
            // Special case for BoxPlot
            | ChartData.BoxPlotYArrays values ->
                bindBoxPlot values (fun value -> value) (fun name index value -> sprintf "Boxplot_%s_%d" name index) false
            | ChartData.BoxPlotXYArrays values ->
                bindBoxPlot values (snd) (fun name index value -> string (fst value)) true

            // Special case for Stacked
            | ChartData.StackedYValues values ->
                bindStackedChart values (fun (dataSeries:Series) seriesValue -> dataSeries.Points.DataBindY [| seriesValue |])
            | ChartData.StackedXYValues values ->
                bindStackedChart values (fun (dataSeries:Series) seriesValue -> dataSeries.Points.DataBindXY((fst seriesValue), ([| snd seriesValue |])))

    // ----------------------------------------------------------------------------------
    // Types that represent data loaded on a chart (and can be used to 
    // modify the data after the chart is created (see also Chart.Create))

    open Internal

    type ChartBinder<'T> = {
        Chart:Chart
        SetCustomProperty: string * 'T -> unit }

    [<AbstractClass>]
    type DataSource() = 
        abstract BindSeries : seq<Series> -> unit

    [<AbstractClass>]
    type DataSourceSingleSeries() =
        inherit DataSource() 
        let mutable series = None
        member internal x.SetDataInternal(data, ?chart:Chart, ?setCustomProperty) =
            match series with
            | None -> failwith "Error: Series has not been set for this data source."
            | Some series -> 
                match (chart, setCustomProperty) with
                | (Some ch, Some property) -> setSeriesData true series data ch property
                | (Some ch, _) -> setSeriesData true series data ch ignore
                | (_, _) -> setSeriesData true series data null ignore                 
        override x.BindSeries(seriesSeq) =
            match List.ofSeq seriesSeq with
            | [single] -> series <- Some single
            | _ -> failwith "Error: Binding multiple series to a data source object that supports only a single series"

    type OneValue() = 
        inherit DataSourceSingleSeries()
        member x.SetData<'TY when 'TY :> IConvertible>(data:seq<'TY>) = 
            base.SetDataInternal(oneY data)
        member x.SetData<'TX, 'TY when 'TX :> IConvertible and 'TY :> IConvertible>(data: seq<'TX * ('TY)>) = 
            base.SetDataInternal(oneXYSeq data)
        member x.SetData<'TX, 'TY when 'TX :> IConvertible and 'TY :> IConvertible>(xvalues:seq<'TX>, yvalues:seq<'TY>) = 
            base.SetDataInternal(oneXY xvalues yvalues)
        member x.SetData<'TY when 'TY :> IConvertible>(data:IObservable<'TY>, ?MaxPoints) = 
            base.SetDataInternal(oneYObs (defaultArg MaxPoints -1) data)
        member x.SetData<'TX, 'TY when 'TY :> IConvertible and 'TX :> IConvertible>(data:IObservable<'TX * ('TY)>, ?MaxPoints) = 
            base.SetDataInternal(oneXYObs (defaultArg MaxPoints -1) data)

    type TwoValue() = 
        inherit DataSourceSingleSeries()
        member x.SetData<'TY1, 'TY2 when 'TY1 :> IConvertible and 'TY2 :> IConvertible>(data:seq<'TY1 * 'TY2>) = 
            base.SetDataInternal(twoY data)
        member x.SetData<'TX, 'TY1, 'TY2 when 'TX :> IConvertible and 'TY1 :> IConvertible and 'TY2 :> IConvertible>(data:seq<'TX * ('TY1 * 'TY2)>) = 
            base.SetDataInternal(twoXYSeq data)
        member x.SetData<'TX, 'TY1, 'TY2 when 'TX :> IConvertible and 'TY1 :> IConvertible and 'TY2 :> IConvertible>(xvalues:seq<'TX>, yvalues1:seq<'TY1>, yvalues2:seq<'TY2>) = 
            base.SetDataInternal(twoXY xvalues yvalues1 yvalues2)
        member x.SetData<'TY1, 'TY2 when 'TY1 :> IConvertible and 'TY2 :> IConvertible>(data:IObservable<'TY1 * 'TY2>, ?MaxPoints) = 
            base.SetDataInternal(twoYObs (defaultArg MaxPoints -1) data)
        member x.SetData<'TX, 'TY1, 'TY2 when 'TY1 :> IConvertible and 'TY2 :> IConvertible and 'TX :> IConvertible>(data:IObservable<'TX * ('TY1 * 'TY2)>, ?MaxPoints) = 
            base.SetDataInternal(twoXYObs (defaultArg MaxPoints -1) data)

    type ThreeValue() = 
        inherit DataSourceSingleSeries()
        member x.SetData<'TY1, 'TY2, 'TY3 when 'TY1 :> IConvertible and 'TY2 :> IConvertible and 'TY3 :> IConvertible >(data:seq<'TY1 * 'TY2 * 'TY3>) = 
            base.SetDataInternal(threeY data)
        member x.SetData<'TX, 'TY1, 'TY2, 'TY3 when 'TX :> IConvertible and 'TY1 :> IConvertible and 'TY2 :> IConvertible and 'TY3 :> IConvertible>(data:seq<'TX * ('TY1 * 'TY2 * 'TY3)>) = 
            base.SetDataInternal(threeXYSeq data)
        member x.SetData<'TX, 'TY1, 'TY2, 'TY3 when 'TX :> IConvertible and 'TY1 :> IConvertible and 'TY2 :> IConvertible and 'TY3 :> IConvertible>(xvalues:seq<'TX>, yvalues1:seq<'TY1>, yvalues2:seq<'TY2>, yvalues3:seq<'TY3>) = 
            base.SetDataInternal(threeXY xvalues yvalues1 yvalues2 yvalues3)
        member x.SetData<'TY1, 'TY2, 'TY3 when 'TY1 :> IConvertible and 'TY2 :> IConvertible and 'TY3 :> IConvertible>(data:IObservable<'TY1 * 'TY2 * 'TY3>, ?MaxPoints) = 
            base.SetDataInternal(threeYObs (defaultArg MaxPoints -1) data)
        member x.SetData<'TX, 'TY1, 'TY2, 'TY3 when 'TY1 :> IConvertible and 'TY2 :> IConvertible and 'TY3 :> IConvertible and 'TX :> IConvertible>(data:IObservable<'TX * ('TY1 * 'TY2 * 'TY3)>, ?MaxPoints) = 
            base.SetDataInternal(threeXYObs (defaultArg MaxPoints -1) data)

    type FourValue() = 
        inherit DataSourceSingleSeries()
        member x.SetData<'TY1, 'TY2, 'TY3, 'TY4 when 'TY1 :> IConvertible and 'TY2 :> IConvertible and 'TY3 :> IConvertible and 'TY4 :> IConvertible>(data:seq<'TY1 * 'TY2 * 'TY3 * 'TY4>) = 
            base.SetDataInternal(fourY data)
        member x.SetData<'TX, 'TY1, 'TY2, 'TY3, 'TY4 when 'TX :> IConvertible and 'TY1 :> IConvertible and 'TY2 :> IConvertible and 'TY3 :> IConvertible and 'TY4 :> IConvertible>(data:seq<'TX * ('TY1 * 'TY2 * 'TY3 * 'TY4)>) = 
            base.SetDataInternal(fourXYSeq data)
        member x.SetData<'TXValues, 'TX, 'TY1, 'TY2, 'TY3, 'TY4 when 'TX :> IConvertible and 'TY1 :> IConvertible and 'TY2 :> IConvertible and 'TY3 :> IConvertible and 'TY4 :> IConvertible>(xvalues:seq<'TX>, yvalues1:seq<'TY1> , yvalues2:seq<'TY2>, yvalues3:seq<'TY3>, yvalues4:seq<'TY4>) = 
            base.SetDataInternal(fourXY xvalues yvalues1 yvalues2 yvalues3 yvalues4)
        member x.SetData<'TY1, 'TY2, 'TY3, 'TY4 when 'TY1 :> IConvertible and 'TY2 :> IConvertible and 'TY3 :> IConvertible and 'TY4 :> IConvertible>(data:IObservable<'TY1 * 'TY2 * 'TY3 * 'TY4>, ?MaxPoints) = 
            base.SetDataInternal(fourYObs (defaultArg MaxPoints -1) data)
        member x.SetData<'TX, 'TY1, 'TY2, 'TY3, 'TY4 when 'TY1 :> IConvertible and 'TY2 :> IConvertible and 'TY3 :> IConvertible and 'TY4 :> IConvertible and 'TX :> IConvertible>(data:IObservable<'TX * ('TY1 * 'TY2 * 'TY3 * 'TY4)>, ?MaxPoints) = 
            base.SetDataInternal(fourXYObs (defaultArg MaxPoints -1) data)

    type MultiValue() = 
        inherit DataSourceSingleSeries()
        member x.SetData(data:seq<'T1 * 'T2 * 'T3 * 'T4 * 'T5 * 'T6>, chartBinder:ChartBinder<string>) = 
            base.SetDataInternal(sixY data, chartBinder.Chart, chartBinder.SetCustomProperty)
        member x.SetData(data:seq<'TX * 'TYValue[]>, chartBinder:ChartBinder<string>) = 
            base.SetDataInternal(sixXYArrBox data, chartBinder.Chart, chartBinder.SetCustomProperty)
        member x.SetData(data:seq<'TYValue[]>, chartBinder:ChartBinder<string>) = 
            base.SetDataInternal(sixYArrBox data, chartBinder.Chart, chartBinder.SetCustomProperty)

    type StackedValue() =
        inherit DataSourceSingleSeries()
        member x.SetData(data: list<list<'TY>>, chartBinder:ChartBinder<string>) =
            base.SetDataInternal(seqY data, chartBinder.Chart)
        member x.SetData(data: list<list<'TX * 'TY>>, chartBinder:ChartBinder<string>) =
            base.SetDataInternal(seqXY data, chartBinder.Chart)


    type DataSourceCombined() = 
        inherit DataSource()
        let mutable seriesTable = dict []
        override x.BindSeries(seriesSeq) =
            seriesTable <- dict [ for s in seriesSeq -> s.Name, s ]
        member x.Find<'TData when 'TData :> DataSource and 'TData : (new : unit -> 'TData)>(name) =
            match seriesTable.TryGetValue(name) with
            | true, obj ->
                // TODO: We do not check if the series has the right data type
                let data = new 'TData()
                data.BindSeries [obj]
                data
            | _ -> failwithf "Error: Series with the name %s not found" name

// ----------------------------------- 
// Charting.ChartTypes.fs
// ----------------------------------- 
open ChartFormUtilities
open ChartData.Internal
open ChartData
open ChartStyles

module ChartTypes = 

    [<AbstractClass>]
    type GenericChart() as self =     
               
        // Events
        let propChangedMargin = Event<float32 * float32 * float32 * float32>()
        let propChangedBackground = Event<Background>()
        let propChangedName = Event<string>()
        let propChangedTitle = Event<Title>()
        let propChangedLegend = Event<Legend>()
        let propChangedCustom = Event<string * obj>()

        let customProperties = new Dictionary<_, _>()

        let mutable area = lazy (
            let area = new ChartArea()
            applyPropertyDefaults (self.ChartType) area
            area)

        let mutable series = lazy (
            let series = new Series()
            applyPropertyDefaults (self.ChartType) series
            series)

        let mutable chart = lazy (
            let ch = new Chart()
            applyPropertyDefaults (self.ChartType) ch
            ch)

        let mutable title = lazy (
            let title = new Title()
            applyPropertyDefaults (self.ChartType) title
            title)

        let mutable legend = lazy (
            let legend = new Legend()
            applyPropertyDefaults (self.ChartType) legend
            legend)

        let mutable name:string = ""

        let evalLazy v =
          let l = lazy v
          l.Force() |> ignore
          l

        let mutable data = ChartData.YValues []
        let mutable margin = (0.0f, 0.0f, 0.0f, 0.0f)
        let titles = new ResizeArray<Title>()
        let legends = new ResizeArray<Legend>()

        abstract ChartType : SeriesChartType
    
        member internal x.Data with get() = data and set v = data <- v
        member internal x.Chart with get() = chart.Value and set v = chart <- evalLazy v
        
        // deal with properties that raise events
        member x.Margin with get() = margin
                        and set v =
                            margin <- v
                            propChangedMargin.Trigger(v)

        member x.Background with set v =
                                applyBackground chart.Value v
                                propChangedBackground.Trigger(v)

        member x.Name with get() = name
                      and set v =
                          name <- v
                          propChangedName.Trigger(v)

        member x.Title with get() = title.Value 
                       and set v = 
                           title <- evalLazy v
                           propChangedTitle.Trigger(v)

        member x.Legend with get() = legend.Value
                        and set v =
                            legend <- evalLazy v
                            propChangedLegend.Trigger(v)        

        // other properties
        member x.Area with get() = area.Value
                      and set v =
                          area <- evalLazy v

        member x.Series with get() = series.Value
                        and set v =
                            series <- evalLazy v

        // internal
        member internal x.Titles = titles
        member internal x.LazyTitle = title
        member internal x.Legends = legends
        member internal x.LazyLegend = legend

        member internal x.LazyChart = chart
        member internal x.LazyArea = area
        member internal x.LazySeries = series
        
        [<CLIEvent>]
        member x.MarginChanged = propChangedMargin.Publish
        [<CLIEvent>]
        member x.BackgroundChanged = propChangedBackground.Publish
        [<CLIEvent>]
        member x.NameChanged = propChangedName.Publish
        [<CLIEvent>]
        member x.TitleChanged = propChangedTitle.Publish
        [<CLIEvent>]
        member x.LegendChanged = propChangedLegend.Publish
        [<CLIEvent>]
        member x.CustomPropertyChanged = propChangedCustom.Publish

        member x.CustomProperties = 
            customProperties :> seq<_>

        member x.GetCustomProperty<'T>(name, def) = 
            match customProperties.TryGetValue name with
            | true, v -> (box v) :?> 'T
            | _ -> def

        member x.SetCustomProperty<'T>(name, v:'T) = 
            customProperties.[name] <- box v
            propChangedCustom.Trigger((name, box v))

        static member internal Create<'T when 'T :> GenericChart and 'T : (new : unit -> 'T)>(data) : 'T =
            let t = new 'T()
            t.Data <- data
            t

        member public x.CopyChartToClipboard() =
            use ms = new IO.MemoryStream()
            x.Chart.SaveImage(ms, ChartImageFormat.Png)
            ms.Seek(0L, IO.SeekOrigin.Begin) |> ignore
            Clipboard.SetImage(Bitmap.FromStream ms)

        member public x.CopyChartToClipboardEmf(control:Control) =
            use ms = new IO.MemoryStream()
            x.Chart.SaveImage(ms, ChartImageFormat.Emf)
            ms.Seek(0L, IO.SeekOrigin.Begin) |> ignore
            use emf = new System.Drawing.Imaging.Metafile(ms)
            ClipboardMetafileHelper.PutEnhMetafileOnClipboard(control.Handle, emf) |> ignore

        member public x.SaveChartAs(filename : string, format : ChartImageFormat) =
            x.Chart.SaveImage(filename, format)

        // property used for chart binding
        member x.ChartBinder with get() =
                                let binder:ChartBinder<string> = { ChartBinder.Chart = x.Chart; ChartBinder.SetCustomProperty = x.SetCustomProperty}
                                binder

    [<AbstractClass>]
    type GenericChart<'TData when 'TData :> DataSource and 'TData : (new : unit -> 'TData)>() = 
        inherit GenericChart()

    type private ColorWrapper(clr:Color) =
        member x.Color = clr
        override x.ToString() =
            if clr.IsEmpty then "Empty" else
            sprintf "%d" (clr.ToArgb()) // clr.R clr.G clr.B

    // ------------------------------------------------------------------------------------
    // [AUTOGENERATED]: Specific chart types for setting custom properties

    /// Displays multiple series of data as stacked areas. The cumulative proportion
    /// of each stacked element is always 100% of the Y
    /// axis.
    type StackedArea100Chart() = 
        inherit GenericChart<OneValue>()

        /// Returns the type of the chart series
        override x.ChartType = SeriesChartType.StackedArea100

        /// <summary>
        ///   Specifies the 3D series depth in pixels.
        /// </summary>
        /// <remarks>Any integer &gt; 0</remarks>
        member x.PixelPointDepth
            with get() = x.GetCustomProperty<int>("PixelPointDepth", 0)
            and set(v) = x.SetCustomProperty<int>("PixelPointDepth", v)

        /// <summary>
        ///   Specifies the 3D gap depth in pixels.
        /// </summary>
        /// <remarks>Any integer &gt; 0</remarks>
        member x.PixelPointGapDepth
            with get() = x.GetCustomProperty<int>("PixelPointGapDepth", 0)
            and set(v) = x.SetCustomProperty<int>("PixelPointGapDepth", v)


    /// Displays multiple series of data as stacked bars. The cumulative
    /// proportion of each stacked element is always 100% of the Y axis.
    type StackedBar100Chart() = 
        inherit GenericChart<OneValue>()

        /// Returns the type of the chart series
        override x.ChartType = SeriesChartType.StackedBar100

        /// Specifies the placement of the data point label.
        member x.BarLabelStyle
            with get() = x.GetCustomProperty<BarLabelStyle>("BarLabelStyle", BarLabelStyle.Outside)
            and set(v) = x.SetCustomProperty<BarLabelStyle>("BarLabelStyle", v)

        /// Specifies the drawing style of data points.
        member x.DrawingStyle
            with get() = x.GetCustomProperty<DrawingStyle>("DrawingStyle", DrawingStyle.Default)
            and set(v) = x.SetCustomProperty<DrawingStyle>("DrawingStyle", v)

        /// <summary>
        ///   Specifies the maximum width of the data point in pixels.
        /// </summary>
        /// <remarks>Any integer &gt; 0</remarks>
        member x.MaxPixelPointWidth
            with get() = x.GetCustomProperty<int>("MaxPixelPointWidth", 0)
            and set(v) = x.SetCustomProperty<int>("MaxPixelPointWidth", v)

        /// <summary>
        ///   Specifies the minimum data point width in pixels.
        /// </summary>
        /// <remarks>Any integer &gt; 0</remarks>
        member x.MinPixelPointWidth
            with get() = x.GetCustomProperty<int>("MinPixelPointWidth", 0)
            and set(v) = x.SetCustomProperty<int>("MinPixelPointWidth", v)

        /// <summary>
        ///   Specifies the 3D series depth in pixels.
        /// </summary>
        /// <remarks>Any integer &gt; 0</remarks>
        member x.PixelPointDepth
            with get() = x.GetCustomProperty<int>("PixelPointDepth", 0)
            and set(v) = x.SetCustomProperty<int>("PixelPointDepth", v)

        /// <summary>
        ///   Specifies the 3D gap depth in pixels.
        /// </summary>
        /// <remarks>Any integer &gt; 0</remarks>
        member x.PixelPointGapDepth
            with get() = x.GetCustomProperty<int>("PixelPointGapDepth", 0)
            and set(v) = x.SetCustomProperty<int>("PixelPointGapDepth", v)

        /// <summary>
        ///   Specifies the data point width in pixels.
        /// </summary>
        /// <remarks>Any integer &gt; 0</remarks>
        member x.PixelPointWidth
            with get() = x.GetCustomProperty<int>("PixelPointWidth", 0)
            and set(v) = x.SetCustomProperty<int>("PixelPointWidth", v)

        /// <summary>
        ///   Specifies the relative data point width.
        /// </summary>
        /// <remarks>Any double from 0 to 2.</remarks>
        member x.PointWidth
            with get() = x.GetCustomProperty<float>("PointWidth", 0.8)
            and set(v) = x.SetCustomProperty<float>("PointWidth", v)

        /// Specifies the name of the stacked group.
        member x.StackedGroupName
            with get() = x.GetCustomProperty<string>("StackedGroupName", "")
            and set(v) = x.SetCustomProperty<string>("StackedGroupName", v)


    /// Displays multiple series of data as stacked columns. The cumulative
    /// proportion of each stacked element is always 100% of the
    /// Y axis.
    type StackedColumn100Chart() = 
        inherit GenericChart<OneValue>()

        /// Returns the type of the chart series
        override x.ChartType = SeriesChartType.StackedColumn100

        /// Specifies the drawing style of data points.
        member x.DrawingStyle
            with get() = x.GetCustomProperty<DrawingStyle>("DrawingStyle", DrawingStyle.Default)
            and set(v) = x.SetCustomProperty<DrawingStyle>("DrawingStyle", v)

        /// <summary>
        ///   Specifies the maximum width of the data point in pixels.
        /// </summary>
        /// <remarks>Any integer &gt; 0</remarks>
        member x.MaxPixelPointWidth
            with get() = x.GetCustomProperty<int>("MaxPixelPointWidth", 0)
            and set(v) = x.SetCustomProperty<int>("MaxPixelPointWidth", v)

        /// <summary>
        ///   Specifies the minimum data point width in pixels.
        /// </summary>
        /// <remarks>Any integer &gt; 0</remarks>
        member x.MinPixelPointWidth
            with get() = x.GetCustomProperty<int>("MinPixelPointWidth", 0)
            and set(v) = x.SetCustomProperty<int>("MinPixelPointWidth", v)

        /// <summary>
        ///   Specifies the 3D series depth in pixels.
        /// </summary>
        /// <remarks>Any integer &gt; 0</remarks>
        member x.PixelPointDepth
            with get() = x.GetCustomProperty<int>("PixelPointDepth", 0)
            and set(v) = x.SetCustomProperty<int>("PixelPointDepth", v)

        /// <summary>
        ///   Specifies the 3D gap depth in pixels.
        /// </summary>
        /// <remarks>Any integer &gt; 0</remarks>
        member x.PixelPointGapDepth
            with get() = x.GetCustomProperty<int>("PixelPointGapDepth", 0)
            and set(v) = x.SetCustomProperty<int>("PixelPointGapDepth", v)

        /// <summary>
        ///   Specifies the data point width in pixels.
        /// </summary>
        /// <remarks>Any integer &gt; 0</remarks>
        member x.PixelPointWidth
            with get() = x.GetCustomProperty<int>("PixelPointWidth", 0)
            and set(v) = x.SetCustomProperty<int>("PixelPointWidth", v)

        /// <summary>
        ///   Specifies the relative data point width.
        /// </summary>
        /// <remarks>Any double from 0 to 2.</remarks>
        member x.PointWidth
            with get() = x.GetCustomProperty<float>("PointWidth", 0.8)
            and set(v) = x.SetCustomProperty<float>("PointWidth", v)

        /// Specifies the name of the stacked group.
        member x.StackedGroupName
            with get() = x.GetCustomProperty<string>("StackedGroupName", "")
            and set(v) = x.SetCustomProperty<string>("StackedGroupName", v)


    /// Emphasizes the degree of change over time and shows the
    /// relationship of the parts to a whole.
    type AreaChart() = 
        inherit GenericChart<OneValue>()

        /// Returns the type of the chart series
        override x.ChartType = SeriesChartType.Area

        /// Specifies the value to be used for empty points.
        member x.EmptyPointValue
            with get() = x.GetCustomProperty<EmptyPointValue>("EmptyPointValue", EmptyPointValue.Average)
            and set(v) = x.SetCustomProperty<EmptyPointValue>("EmptyPointValue", v)

        /// Specifies the label position of the data point.
        member x.LabelStyle
            with get() = x.GetCustomProperty<LabelStyle>("LabelStyle", LabelStyle.Auto)
            and set(v) = x.SetCustomProperty<LabelStyle>("LabelStyle", v)

        /// <summary>
        ///   Specifies the 3D series depth in pixels.
        /// </summary>
        /// <remarks>Any integer &gt; 0</remarks>
        member x.PixelPointDepth
            with get() = x.GetCustomProperty<int>("PixelPointDepth", 0)
            and set(v) = x.SetCustomProperty<int>("PixelPointDepth", v)

        /// <summary>
        ///   Specifies the 3D gap depth in pixels.
        /// </summary>
        /// <remarks>Any integer &gt; 0</remarks>
        member x.PixelPointGapDepth
            with get() = x.GetCustomProperty<int>("PixelPointGapDepth", 0)
            and set(v) = x.SetCustomProperty<int>("PixelPointGapDepth", v)

        /// Specifies whether marker lines are displayed when rendered in 3D.
        member x.ShowMarkerLines
            with get() = x.GetCustomProperty<bool>("ShowMarkerLines", false)
            and set(v) = x.SetCustomProperty<bool>("ShowMarkerLines", v)


    /// Illustrates comparisons among individual items.
    type BarChart() = 
        inherit GenericChart<OneValue>()

        /// Returns the type of the chart series
        override x.ChartType = SeriesChartType.Bar

        /// Specifies the placement of the data point label.
        member x.BarLabelStyle
            with get() = x.GetCustomProperty<BarLabelStyle>("BarLabelStyle", BarLabelStyle.Outside)
            and set(v) = x.SetCustomProperty<BarLabelStyle>("BarLabelStyle", v)

        /// Specifies the drawing style of data points.
        member x.DrawingStyle
            with get() = x.GetCustomProperty<DrawingStyle>("DrawingStyle", DrawingStyle.Default)
            and set(v) = x.SetCustomProperty<DrawingStyle>("DrawingStyle", v)

        /// Specifies whether series of the same chart type are drawn
        /// next to each other instead of overlapping each other.
        member x.DrawSideBySide
            with get() = x.GetCustomProperty<DrawSideBySide>("DrawSideBySide", DrawSideBySide.Auto)
            and set(v) = x.SetCustomProperty<DrawSideBySide>("DrawSideBySide", v)

        /// Specifies the value to be used for empty points.
        member x.EmptyPointValue
            with get() = x.GetCustomProperty<EmptyPointValue>("EmptyPointValue", EmptyPointValue.Average)
            and set(v) = x.SetCustomProperty<EmptyPointValue>("EmptyPointValue", v)

        /// <summary>
        ///   Specifies the maximum width of the data point in pixels.
        /// </summary>
        /// <remarks>Any integer &gt; 0</remarks>
        member x.MaxPixelPointWidth
            with get() = x.GetCustomProperty<int>("MaxPixelPointWidth", 0)
            and set(v) = x.SetCustomProperty<int>("MaxPixelPointWidth", v)

        /// <summary>
        ///   Specifies the minimum data point width in pixels.
        /// </summary>
        /// <remarks>Any integer &gt; 0</remarks>
        member x.MinPixelPointWidth
            with get() = x.GetCustomProperty<int>("MinPixelPointWidth", 0)
            and set(v) = x.SetCustomProperty<int>("MinPixelPointWidth", v)

        /// <summary>
        ///   Specifies the 3D series depth in pixels.
        /// </summary>
        /// <remarks>Any integer &gt; 0</remarks>
        member x.PixelPointDepth
            with get() = x.GetCustomProperty<int>("PixelPointDepth", 0)
            and set(v) = x.SetCustomProperty<int>("PixelPointDepth", v)

        /// <summary>
        ///   Specifies the 3D gap depth in pixels.
        /// </summary>
        /// <remarks>Any integer &gt; 0</remarks>
        member x.PixelPointGapDepth
            with get() = x.GetCustomProperty<int>("PixelPointGapDepth", 0)
            and set(v) = x.SetCustomProperty<int>("PixelPointGapDepth", v)

        /// <summary>
        ///   Specifies the data point width in pixels.
        /// </summary>
        /// <remarks>Any integer &gt; 0</remarks>
        member x.PixelPointWidth
            with get() = x.GetCustomProperty<int>("PixelPointWidth", 0)
            and set(v) = x.SetCustomProperty<int>("PixelPointWidth", v)

        /// <summary>
        ///   Specifies the relative data point width.
        /// </summary>
        /// <remarks>Any double from 0 to 2.</remarks>
        member x.PointWidth
            with get() = x.GetCustomProperty<float>("PointWidth", 0.8)
            and set(v) = x.SetCustomProperty<float>("PointWidth", v)


    /// Consists of one or more box symbols that summarize the
    /// distribution of the data within one or more data sets.
    type BoxPlotChart() = 
        inherit GenericChart<MultiValue>()

        /// Returns the type of the chart series
        override x.ChartType = SeriesChartType.BoxPlot

        /// <summary>
        ///   Specifies the percentile value of the box of the Box
        ///   Plot chart.
        /// </summary>
        /// <remarks>Any integer from 0 to 50.</remarks>
        member x.BoxPlotPercentile
            with get() = x.GetCustomProperty<int>("BoxPlotPercentile", 25)
            and set(v) = x.SetCustomProperty<int>("BoxPlotPercentile", v)

        /// Specifies the name of the series to be used as
        /// the data source for the Box Plot chart.
        member x.BoxPlotSeries
            with get() = x.GetCustomProperty<string>("BoxPlotSeries", "")
            and set(v) = x.SetCustomProperty<string>("BoxPlotSeries", v)

        /// Specifies whether to display the average value for the Box
        /// Plot chart.
        member x.BoxPlotShowAverage
            with get() = x.GetCustomProperty<bool>("BoxPlotShowAverage", true)
            and set(v) = x.SetCustomProperty<bool>("BoxPlotShowAverage", v)

        /// Specifies whether to display the median value for the Box
        /// Plot chart.
        member x.BoxPlotShowMedian
            with get() = x.GetCustomProperty<bool>("BoxPlotShowMedian", true)
            and set(v) = x.SetCustomProperty<bool>("BoxPlotShowMedian", v)

        /// Specifies whether the unusual values value for the Box Plot
        /// chart will be shown.
        member x.BoxPlotShowUnusualValues
            with get() = x.GetCustomProperty<bool>("BoxPlotShowUnusualValues", true)
            and set(v) = x.SetCustomProperty<bool>("BoxPlotShowUnusualValues", v)

        /// <summary>
        ///   Specifies the percentile value of the whiskers of the Box
        ///   Plot chart.
        /// </summary>
        /// <remarks>Any integer from 0 to 50.</remarks>
        member x.BoxPlotWhiskerPercentile
            with get() = x.GetCustomProperty<int>("BoxPlotWhiskerPercentile", 10)
            and set(v) = x.SetCustomProperty<int>("BoxPlotWhiskerPercentile", v)

        /// Specifies whether series of the same chart type are drawn
        /// next to each other instead of overlapping each other.
        member x.DrawSideBySide
            with get() = x.GetCustomProperty<DrawSideBySide>("DrawSideBySide", DrawSideBySide.Auto)
            and set(v) = x.SetCustomProperty<DrawSideBySide>("DrawSideBySide", v)

        /// <summary>
        ///   Specifies the maximum width of the data point in pixels.
        /// </summary>
        /// <remarks>Any integer &gt; 0</remarks>
        member x.MaxPixelPointWidth
            with get() = x.GetCustomProperty<int>("MaxPixelPointWidth", 0)
            and set(v) = x.SetCustomProperty<int>("MaxPixelPointWidth", v)

        /// <summary>
        ///   Specifies the minimum data point width in pixels.
        /// </summary>
        /// <remarks>Any integer &gt; 0</remarks>
        member x.MinPixelPointWidth
            with get() = x.GetCustomProperty<int>("MinPixelPointWidth", 0)
            and set(v) = x.SetCustomProperty<int>("MinPixelPointWidth", v)

        /// <summary>
        ///   Specifies the 3D series depth in pixels.
        /// </summary>
        /// <remarks>Any integer &gt; 0</remarks>
        member x.PixelPointDepth
            with get() = x.GetCustomProperty<int>("PixelPointDepth", 0)
            and set(v) = x.SetCustomProperty<int>("PixelPointDepth", v)

        /// <summary>
        ///   Specifies the 3D gap depth in pixels.
        /// </summary>
        /// <remarks>Any integer &gt; 0</remarks>
        member x.PixelPointGapDepth
            with get() = x.GetCustomProperty<int>("PixelPointGapDepth", 0)
            and set(v) = x.SetCustomProperty<int>("PixelPointGapDepth", v)

        /// <summary>
        ///   Specifies the data point width in pixels.
        /// </summary>
        /// <remarks>Any integer &gt; 0</remarks>
        member x.PixelPointWidth
            with get() = x.GetCustomProperty<int>("PixelPointWidth", 0)
            and set(v) = x.SetCustomProperty<int>("PixelPointWidth", v)

        /// <summary>
        ///   Specifies the relative data point width.
        /// </summary>
        /// <remarks>Any double from 0 to 2.</remarks>
        member x.PointWidth
            with get() = x.GetCustomProperty<float>("PointWidth", 0.8)
            and set(v) = x.SetCustomProperty<float>("PointWidth", v)


    /// A variation of the Point chart type, where the data
    /// points are replaced by bubbles of different sizes.
    type BubbleChart() = 
        inherit GenericChart<TwoValue>()

        /// Returns the type of the chart series
        override x.ChartType = SeriesChartType.Bubble

        /// <summary>
        ///   Specifies the maximum size of the bubble radius as a
        ///   percentage of the chart area size.
        /// </summary>
        /// <remarks>Any integer from 0 to 100.</remarks>
        member x.BubbleMaxSize
            with get() = x.GetCustomProperty<int>("BubbleMaxSize", 15)
            and set(v) = x.SetCustomProperty<int>("BubbleMaxSize", v)

        /// <summary>
        ///   Specifies the minimum size of the bubble radius as a
        ///   percentage of the chart area size.
        /// </summary>
        /// <remarks>Any integer from 0 to 100.</remarks>
        member x.BubbleMinSize
            with get() = x.GetCustomProperty<int>("BubbleMinSize", 3)
            and set(v) = x.SetCustomProperty<int>("BubbleMinSize", v)

        /// <summary>
        ///   Specifies the maximum bubble size, which is a percentage of
        ///   the chart area that is set by BubbleMaxSize.
        /// </summary>
        /// <remarks>Any double.</remarks>
        member x.BubbleScaleMax
            with get() = x.GetCustomProperty<float>("BubbleScaleMax", 15.0)
            and set(v) = x.SetCustomProperty<float>("BubbleScaleMax", v)

        /// <summary>
        ///   Specifies the minimum bubble size, which is a percentage of
        ///   the chart area that is set by BubbleMinSize.
        /// </summary>
        /// <remarks>Any double.</remarks>
        member x.BubbleScaleMin
            with get() = x.GetCustomProperty<float>("BubbleScaleMin", 3.0)
            and set(v) = x.SetCustomProperty<float>("BubbleScaleMin", v)

        /// Specifies whether to use the bubble size as the data
        /// point label.
        member x.BubbleUseSizeForLabel
            with get() = x.GetCustomProperty<bool>("BubbleUseSizeForLabel", false)
            and set(v) = x.SetCustomProperty<bool>("BubbleUseSizeForLabel", v)

        /// Specifies the value to be used for empty points.
        member x.EmptyPointValue
            with get() = x.GetCustomProperty<EmptyPointValue>("EmptyPointValue", EmptyPointValue.Average)
            and set(v) = x.SetCustomProperty<EmptyPointValue>("EmptyPointValue", v)

        /// Specifies the label position of the data point.
        member x.LabelStyle
            with get() = x.GetCustomProperty<LabelStyle>("LabelStyle", LabelStyle.Auto)
            and set(v) = x.SetCustomProperty<LabelStyle>("LabelStyle", v)

        /// <summary>
        ///   Specifies the 3D series depth in pixels.
        /// </summary>
        /// <remarks>Any integer &gt; 0</remarks>
        member x.PixelPointDepth
            with get() = x.GetCustomProperty<int>("PixelPointDepth", 0)
            and set(v) = x.SetCustomProperty<int>("PixelPointDepth", v)

        /// <summary>
        ///   Specifies the 3D gap depth in pixels.
        /// </summary>
        /// <remarks>Any integer &gt; 0</remarks>
        member x.PixelPointGapDepth
            with get() = x.GetCustomProperty<int>("PixelPointGapDepth", 0)
            and set(v) = x.SetCustomProperty<int>("PixelPointGapDepth", v)


    /// Used to display stock information using high, low, open and
    /// close values.
    type CandlestickChart() = 
        inherit GenericChart<FourValue>()

        /// Returns the type of the chart series
        override x.ChartType = SeriesChartType.Candlestick

        /// Specifies the Y value to use as the data point
        /// label.
        member x.LabelValueType
            with get() = x.GetCustomProperty<LabelValueType>("LabelValueType", LabelValueType.Close)
            and set(v) = x.SetCustomProperty<LabelValueType>("LabelValueType", v)

        /// <summary>
        ///   Specifies the maximum width of the data point in pixels.
        /// </summary>
        /// <remarks>Any integer &gt; 0</remarks>
        member x.MaxPixelPointWidth
            with get() = x.GetCustomProperty<int>("MaxPixelPointWidth", 0)
            and set(v) = x.SetCustomProperty<int>("MaxPixelPointWidth", v)

        /// <summary>
        ///   Specifies the minimum data point width in pixels.
        /// </summary>
        /// <remarks>Any integer &gt; 0</remarks>
        member x.MinPixelPointWidth
            with get() = x.GetCustomProperty<int>("MinPixelPointWidth", 0)
            and set(v) = x.SetCustomProperty<int>("MinPixelPointWidth", v)

        /// <summary>
        ///   Specifies the 3D series depth in pixels.
        /// </summary>
        /// <remarks>Any integer &gt; 0</remarks>
        member x.PixelPointDepth
            with get() = x.GetCustomProperty<int>("PixelPointDepth", 0)
            and set(v) = x.SetCustomProperty<int>("PixelPointDepth", v)

        /// <summary>
        ///   Specifies the 3D gap depth in pixels.
        /// </summary>
        /// <remarks>Any integer &gt; 0</remarks>
        member x.PixelPointGapDepth
            with get() = x.GetCustomProperty<int>("PixelPointGapDepth", 0)
            and set(v) = x.SetCustomProperty<int>("PixelPointGapDepth", v)

        /// <summary>
        ///   Specifies the data point width in pixels.
        /// </summary>
        /// <remarks>Any integer &gt; 0</remarks>
        member x.PixelPointWidth
            with get() = x.GetCustomProperty<int>("PixelPointWidth", 0)
            and set(v) = x.SetCustomProperty<int>("PixelPointWidth", v)

        /// <summary>
        ///   Specifies the relative data point width.
        /// </summary>
        /// <remarks>Any double from 0 to 2.</remarks>
        member x.PointWidth
            with get() = x.GetCustomProperty<float>("PointWidth", 0.8)
            and set(v) = x.SetCustomProperty<float>("PointWidth", v)

        /// Specifies the data point color to use to indicate a
        /// decreasing trend.
        member x.PriceDownColor
            with get() = x.GetCustomProperty<ColorWrapper>("PriceDownColor", ColorWrapper(Color.Empty)).Color
            and set(v) = x.SetCustomProperty<ColorWrapper>("PriceDownColor", ColorWrapper(v))

        /// Specifies the data point color that indicates an increasing trend.
        member x.PriceUpColor
            with get() = x.GetCustomProperty<ColorWrapper>("PriceUpColor", ColorWrapper(Color.Empty)).Color
            and set(v) = x.SetCustomProperty<ColorWrapper>("PriceUpColor", ColorWrapper(v))


    /// Uses a sequence of columns to compare values across categories.
    type ColumnChart() = 
        inherit GenericChart<OneValue>()

        /// Returns the type of the chart series
        override x.ChartType = SeriesChartType.Column

        /// Specifies the drawing style of data points.
        member x.DrawingStyle
            with get() = x.GetCustomProperty<DrawingStyle>("DrawingStyle", DrawingStyle.Default)
            and set(v) = x.SetCustomProperty<DrawingStyle>("DrawingStyle", v)

        /// Specifies whether series of the same chart type are drawn
        /// next to each other instead of overlapping each other.
        member x.DrawSideBySide
            with get() = x.GetCustomProperty<DrawSideBySide>("DrawSideBySide", DrawSideBySide.Auto)
            and set(v) = x.SetCustomProperty<DrawSideBySide>("DrawSideBySide", v)

        /// Specifies the value to be used for empty points.
        member x.EmptyPointValue
            with get() = x.GetCustomProperty<EmptyPointValue>("EmptyPointValue", EmptyPointValue.Average)
            and set(v) = x.SetCustomProperty<EmptyPointValue>("EmptyPointValue", v)

        /// Specifies the label position of the data point.
        member x.LabelStyle
            with get() = x.GetCustomProperty<LabelStyle>("LabelStyle", LabelStyle.Auto)
            and set(v) = x.SetCustomProperty<LabelStyle>("LabelStyle", v)

        /// <summary>
        ///   Specifies the maximum width of the data point in pixels.
        /// </summary>
        /// <remarks>Any integer &gt; 0</remarks>
        member x.MaxPixelPointWidth
            with get() = x.GetCustomProperty<int>("MaxPixelPointWidth", 0)
            and set(v) = x.SetCustomProperty<int>("MaxPixelPointWidth", v)

        /// <summary>
        ///   Specifies the minimum data point width in pixels.
        /// </summary>
        /// <remarks>Any integer &gt; 0</remarks>
        member x.MinPixelPointWidth
            with get() = x.GetCustomProperty<int>("MinPixelPointWidth", 0)
            and set(v) = x.SetCustomProperty<int>("MinPixelPointWidth", v)

        /// <summary>
        ///   Specifies the 3D series depth in pixels.
        /// </summary>
        /// <remarks>Any integer &gt; 0</remarks>
        member x.PixelPointDepth
            with get() = x.GetCustomProperty<int>("PixelPointDepth", 0)
            and set(v) = x.SetCustomProperty<int>("PixelPointDepth", v)

        /// <summary>
        ///   Specifies the 3D gap depth in pixels.
        /// </summary>
        /// <remarks>Any integer &gt; 0</remarks>
        member x.PixelPointGapDepth
            with get() = x.GetCustomProperty<int>("PixelPointGapDepth", 0)
            and set(v) = x.SetCustomProperty<int>("PixelPointGapDepth", v)

        /// <summary>
        ///   Specifies the data point width in pixels.
        /// </summary>
        /// <remarks>Any integer &gt; 0</remarks>
        member x.PixelPointWidth
            with get() = x.GetCustomProperty<int>("PixelPointWidth", 0)
            and set(v) = x.SetCustomProperty<int>("PixelPointWidth", v)

        /// <summary>
        ///   Specifies the relative data point width.
        /// </summary>
        /// <remarks>Any double from 0 to 2.</remarks>
        member x.PointWidth
            with get() = x.GetCustomProperty<float>("PointWidth", 0.8)
            and set(v) = x.SetCustomProperty<float>("PointWidth", v)


    /// Similar to the Pie chart type, except that it has
    /// a hole in the center.
    type DoughnutChart() = 
        inherit GenericChart<OneValue>()

        /// Returns the type of the chart series
        override x.ChartType = SeriesChartType.Doughnut

        /// <summary>
        ///   Specifies the 3D label line size as a percentage of
        ///   the default size.
        /// </summary>
        /// <remarks>Any integer from 30 to 200.</remarks>
        member x.LabelLineSize3D
            with get() = x.GetCustomProperty<int>("3DLabelLineSize", 100)
            and set(v) = x.SetCustomProperty<int>("3DLabelLineSize", v)

        /// Specifies the color of the collected pie or doughnut slice.
        member x.CollectedColor
            with get() = x.GetCustomProperty<ColorWrapper>("CollectedColor", ColorWrapper(Color.Empty)).Color
            and set(v) = x.SetCustomProperty<ColorWrapper>("CollectedColor", ColorWrapper(v))

        /// Specifies the label of the collected pie slice.
        member x.CollectedLabel
            with get() = x.GetCustomProperty<string>("CollectedLabel", "")
            and set(v) = x.SetCustomProperty<string>("CollectedLabel", v)

        /// Specifies the legend text for the collected pie slice.
        member x.CollectedLegendText
            with get() = x.GetCustomProperty<string>("CollectedLegendText", "")
            and set(v) = x.SetCustomProperty<string>("CollectedLegendText", v)

        /// Specifies whether the collected pie slice will be shown as
        /// exploded.
        member x.CollectedSliceExploded
            with get() = x.GetCustomProperty<bool>("CollectedSliceExploded", true)
            and set(v) = x.SetCustomProperty<bool>("CollectedSliceExploded", v)

        /// <summary>
        ///   Specifies the threshold value for collecting small pie slices.
        /// </summary>
        /// <remarks>Any double between 0 and 100 if CollectedThresholdUsePercent is true; otherwise, any double &gt; 0.</remarks>
        member x.CollectedThreshold
            with get() = x.GetCustomProperty<float>("CollectedThreshold", 0.0)
            and set(v) = x.SetCustomProperty<float>("CollectedThreshold", v)

        /// Specifies whether to use the collected threshold value as a
        /// percentage.
        member x.CollectedThresholdUsePercent
            with get() = x.GetCustomProperty<bool>("CollectedThresholdUsePercent", true)
            and set(v) = x.SetCustomProperty<bool>("CollectedThresholdUsePercent", v)

        /// Specifies the tooltip text of the collected pie slice.
        member x.CollectedToolTip
            with get() = x.GetCustomProperty<string>("CollectedToolTip", "")
            and set(v) = x.SetCustomProperty<string>("CollectedToolTip", v)

        /// <summary>
        ///   Specifies the radius of the doughnut portion in the Doughnut
        ///   chart.
        /// </summary>
        /// <remarks>Any integer from 0 to 100.</remarks>
        member x.DoughnutRadius
            with get() = x.GetCustomProperty<int>("DoughnutRadius", 60)
            and set(v) = x.SetCustomProperty<int>("DoughnutRadius", v)

        /// Specifies whether the Pie or Doughnut data point is exploded.
        member x.Exploded
            with get() = x.GetCustomProperty<bool>("Exploded", false)
            and set(v) = x.SetCustomProperty<bool>("Exploded", v)

        /// <summary>
        ///   Specifies the size of the horizontal segment of the callout
        ///   line.
        /// </summary>
        /// <remarks>Any integer from 0 to 100.</remarks>
        member x.LabelsHorizontalLineSize
            with get() = x.GetCustomProperty<int>("LabelsHorizontalLineSize", 1)
            and set(v) = x.SetCustomProperty<int>("LabelsHorizontalLineSize", v)

        /// <summary>
        ///   Specifies the size of the radial segment of the callout
        ///   line.
        /// </summary>
        /// <remarks>Any integer from 0 to 100.</remarks>
        member x.LabelsRadialLineSize
            with get() = x.GetCustomProperty<int>("LabelsRadialLineSize", 1)
            and set(v) = x.SetCustomProperty<int>("LabelsRadialLineSize", v)

        /// <summary>
        ///   Specifies the minimum pie or doughnut size.
        /// </summary>
        /// <remarks>Any integer from 10 to 70.</remarks>
        member x.MinimumRelativePieSize
            with get() = x.GetCustomProperty<int>("MinimumRelativePieSize", 30)
            and set(v) = x.SetCustomProperty<int>("MinimumRelativePieSize", v)

        /// Specifies the drawing style of the data points.
        member x.PieDrawingStyle
            with get() = x.GetCustomProperty<PieDrawingStyle>("PieDrawingStyle", PieDrawingStyle.Default)
            and set(v) = x.SetCustomProperty<PieDrawingStyle>("PieDrawingStyle", v)

        /// Specifies the label style of the data points.
        member x.PieLabelStyle
            with get() = x.GetCustomProperty<PieLabelStyle>("PieLabelStyle", PieLabelStyle.Inside)
            and set(v) = x.SetCustomProperty<PieLabelStyle>("PieLabelStyle", v)

        /// Specifies the color of the radial and horizontal segments of
        /// the callout lines.
        member x.PieLineColor
            with get() = x.GetCustomProperty<ColorWrapper>("PieLineColor", ColorWrapper(Color.Black)).Color
            and set(v) = x.SetCustomProperty<ColorWrapper>("PieLineColor", ColorWrapper(v))

        /// <summary>
        ///   Specifies the angle of the data point in the Pie
        ///   or Doughnut chart.
        /// </summary>
        /// <remarks>Any integer from 0 to 360.</remarks>
        member x.PieStartAngle
            with get() = x.GetCustomProperty<int>("PieStartAngle", 90)
            and set(v) = x.SetCustomProperty<int>("PieStartAngle", v)


    /// Consists of lines with markers that are used to display
    /// statistical information about the data displayed in a graph.
    type ErrorBarChart() = 
        inherit GenericChart<ThreeValue>()

        /// Returns the type of the chart series
        override x.ChartType = SeriesChartType.ErrorBar

        /// Specifies whether series of the same chart type are drawn
        /// next to each other instead of overlapping each other.
        member x.DrawSideBySide
            with get() = x.GetCustomProperty<DrawSideBySide>("DrawSideBySide", DrawSideBySide.Auto)
            and set(v) = x.SetCustomProperty<DrawSideBySide>("DrawSideBySide", v)

        /// Specifies the appearance of the marker at the center value
        /// of the error bar.
        member x.ErrorBarCenterMarkerStyle
            with get() = x.GetCustomProperty<ErrorBarCenterMarkerStyle>("ErrorBarCenterMarkerStyle", ErrorBarCenterMarkerStyle.None)
            and set(v) = x.SetCustomProperty<ErrorBarCenterMarkerStyle>("ErrorBarCenterMarkerStyle", v)

        /// Specifies the name of the series to be used as
        /// the data source for the Error Bar chart calculations.
        member x.ErrorBarSeries
            with get() = x.GetCustomProperty<string>("ErrorBarSeries", "")
            and set(v) = x.SetCustomProperty<string>("ErrorBarSeries", v)

        /// Specifies the visibility of the upper and lower error values.
        member x.ErrorBarStyle
            with get() = x.GetCustomProperty<ErrorBarStyle>("ErrorBarStyle", ErrorBarStyle.Both)
            and set(v) = x.SetCustomProperty<ErrorBarStyle>("ErrorBarStyle", v)

        /// Specifies how the upper and lower error values are calculated
        /// for the center values of the ErrorBarSeries.
        member x.ErrorBarType
            with get() = x.GetCustomProperty<ErrorBarType>("ErrorBarType", ErrorBarType.FixedValue)
            and set(v) = x.SetCustomProperty<ErrorBarType>("ErrorBarType", v)

        /// <summary>
        ///   Specifies the maximum width of the data point in pixels.
        /// </summary>
        /// <remarks>Any integer &gt; 0</remarks>
        member x.MaxPixelPointWidth
            with get() = x.GetCustomProperty<int>("MaxPixelPointWidth", 0)
            and set(v) = x.SetCustomProperty<int>("MaxPixelPointWidth", v)

        /// <summary>
        ///   Specifies the minimum data point width in pixels.
        /// </summary>
        /// <remarks>Any integer &gt; 0</remarks>
        member x.MinPixelPointWidth
            with get() = x.GetCustomProperty<int>("MinPixelPointWidth", 0)
            and set(v) = x.SetCustomProperty<int>("MinPixelPointWidth", v)

        /// <summary>
        ///   Specifies the 3D series depth in pixels.
        /// </summary>
        /// <remarks>Any integer &gt; 0</remarks>
        member x.PixelPointDepth
            with get() = x.GetCustomProperty<int>("PixelPointDepth", 0)
            and set(v) = x.SetCustomProperty<int>("PixelPointDepth", v)

        /// <summary>
        ///   Specifies the 3D gap depth in pixels.
        /// </summary>
        /// <remarks>Any integer &gt; 0</remarks>
        member x.PixelPointGapDepth
            with get() = x.GetCustomProperty<int>("PixelPointGapDepth", 0)
            and set(v) = x.SetCustomProperty<int>("PixelPointGapDepth", v)

        /// <summary>
        ///   Specifies the data point width in pixels.
        /// </summary>
        /// <remarks>Any integer &gt; 0</remarks>
        member x.PixelPointWidth
            with get() = x.GetCustomProperty<int>("PixelPointWidth", 0)
            and set(v) = x.SetCustomProperty<int>("PixelPointWidth", v)

        /// <summary>
        ///   Specifies the relative data point width.
        /// </summary>
        /// <remarks>Any double from 0 to 2.</remarks>
        member x.PointWidth
            with get() = x.GetCustomProperty<float>("PointWidth", 0.8)
            and set(v) = x.SetCustomProperty<float>("PointWidth", v)


    /// A variation of the Line chart that significantly reduces the
    /// drawing time of a series that contains a very large
    /// number of data points.
    type FastLineChart() = 
        inherit GenericChart<OneValue>()

        /// Returns the type of the chart series
        override x.ChartType = SeriesChartType.FastLine

        /// <summary>
        ///   Specifies the 3D series depth in pixels.
        /// </summary>
        /// <remarks>Any integer &gt; 0</remarks>
        member x.PixelPointDepth
            with get() = x.GetCustomProperty<int>("PixelPointDepth", 0)
            and set(v) = x.SetCustomProperty<int>("PixelPointDepth", v)

        /// <summary>
        ///   Specifies the 3D gap depth in pixels.
        /// </summary>
        /// <remarks>Any integer &gt; 0</remarks>
        member x.PixelPointGapDepth
            with get() = x.GetCustomProperty<int>("PixelPointGapDepth", 0)
            and set(v) = x.SetCustomProperty<int>("PixelPointGapDepth", v)


    /// A variation of the Point chart type that significantly reduces
    /// the drawing time of a series that contains a very
    /// large number of data points.
    type FastPointChart() = 
        inherit GenericChart<OneValue>()

        /// Returns the type of the chart series
        override x.ChartType = SeriesChartType.FastPoint


    /// Displays in a funnel shape data that equals 100% when
    /// totaled.
    type FunnelChart() = 
        inherit GenericChart<OneValue>()

        /// Returns the type of the chart series
        override x.ChartType = SeriesChartType.Funnel

        /// Specifies the line color of the callout for the data
        /// point labels of Funnel or Pyramid charts.
        member x.CalloutLineColor
            with get() = x.GetCustomProperty<ColorWrapper>("CalloutLineColor", ColorWrapper(Color.Empty)).Color
            and set(v) = x.SetCustomProperty<ColorWrapper>("CalloutLineColor", ColorWrapper(v))

        /// Specifies the 3D drawing style of the Funnel chart type.
        member x.Funnel3DDrawingStyle
            with get() = x.GetCustomProperty<Funnel3DDrawingStyle>("Funnel3DDrawingStyle", Funnel3DDrawingStyle.SquareBase)
            and set(v) = x.SetCustomProperty<Funnel3DDrawingStyle>("Funnel3DDrawingStyle", v)

        /// <summary>
        ///   Specifies the 3D rotation angle of the Funnel chart type.
        /// </summary>
        /// <remarks>Any integer from -10 to 10.</remarks>
        member x.Funnel3DRotationAngle
            with get() = x.GetCustomProperty<int>("Funnel3DRotationAngle", 5)
            and set(v) = x.SetCustomProperty<int>("Funnel3DRotationAngle", v)

        /// Specifies the data point label placement of the Funnel chart
        /// type when the FunnelLabelStyle is set to Inside.
        member x.FunnelInsideLabelAlignment
            with get() = x.GetCustomProperty<FunnelInsideLabelAlignment>("FunnelInsideLabelAlignment", FunnelInsideLabelAlignment.Center)
            and set(v) = x.SetCustomProperty<FunnelInsideLabelAlignment>("FunnelInsideLabelAlignment", v)

        /// Specifies the data point label style of the Funnel chart
        /// type.
        member x.FunnelLabelStyle
            with get() = x.GetCustomProperty<FunnelLabelStyle>("FunnelLabelStyle", FunnelLabelStyle.OutsideInColumn)
            and set(v) = x.SetCustomProperty<FunnelLabelStyle>("FunnelLabelStyle", v)

        /// <summary>
        ///   Specifies the minimum height of a data point in the
        ///   Funnel chart, measured in relative coordinates.
        /// </summary>
        /// <remarks>Any integer from 0 to 100.</remarks>
        member x.FunnelMinPointHeight
            with get() = x.GetCustomProperty<int>("FunnelMinPointHeight", 0)
            and set(v) = x.SetCustomProperty<int>("FunnelMinPointHeight", v)

        /// <summary>
        ///   Specifies the neck height of the Funnel chart type.
        /// </summary>
        /// <remarks>Any integer from 0 to 100.</remarks>
        member x.FunnelNeckHeight
            with get() = x.GetCustomProperty<int>("FunnelNeckHeight", 5)
            and set(v) = x.SetCustomProperty<int>("FunnelNeckHeight", v)

        /// <summary>
        ///   Specifies the neck width of the Funnel chart type.
        /// </summary>
        /// <remarks>Any integer from 0 to 100.</remarks>
        member x.FunnelNeckWidth
            with get() = x.GetCustomProperty<int>("FunnelNeckWidth", 5)
            and set(v) = x.SetCustomProperty<int>("FunnelNeckWidth", v)

        /// Placement of the data point label in the Funnel chart
        /// when FunnelLabelStyle is set to Outside or OutsideInColumn.
        member x.FunnelOutsideLabelPlacement
            with get() = x.GetCustomProperty<FunnelOutsideLabelPlacement>("FunnelOutsideLabelPlacement", FunnelOutsideLabelPlacement.Right)
            and set(v) = x.SetCustomProperty<FunnelOutsideLabelPlacement>("FunnelOutsideLabelPlacement", v)

        /// <summary>
        ///   Specifies the gap size between the points of a Funnel
        ///   chart, measured in relative coordinates.
        /// </summary>
        /// <remarks>Any integer from 0 to 100.</remarks>
        member x.FunnelPointGap
            with get() = x.GetCustomProperty<int>("FunnelPointGap", 0)
            and set(v) = x.SetCustomProperty<int>("FunnelPointGap", v)

        /// Specifies the style of the Funnel chart type.
        member x.FunnelStyle
            with get() = x.GetCustomProperty<FunnelStyle>("FunnelStyle", FunnelStyle.YIsHeight)
            and set(v) = x.SetCustomProperty<FunnelStyle>("FunnelStyle", v)


    /// Displays a series of connecting vertical lines where the thickness
    /// and direction of the lines are dependent on the action
    /// of the price value.
    type KagiChart() = 
        inherit GenericChart<OneValue>()

        /// Returns the type of the chart series
        override x.ChartType = SeriesChartType.Kagi

        /// <summary>
        ///   Specifies the 3D series depth in pixels.
        /// </summary>
        /// <remarks>Any integer &gt; 0</remarks>
        member x.PixelPointDepth
            with get() = x.GetCustomProperty<int>("PixelPointDepth", 0)
            and set(v) = x.SetCustomProperty<int>("PixelPointDepth", v)

        /// <summary>
        ///   Specifies the 3D gap depth in pixels.
        /// </summary>
        /// <remarks>Any integer &gt; 0</remarks>
        member x.PixelPointGapDepth
            with get() = x.GetCustomProperty<int>("PixelPointGapDepth", 0)
            and set(v) = x.SetCustomProperty<int>("PixelPointGapDepth", v)

        /// Specifies the data point color that indicates an increasing trend.
        member x.PriceUpColor
            with get() = x.GetCustomProperty<ColorWrapper>("PriceUpColor", ColorWrapper(Color.Empty)).Color
            and set(v) = x.SetCustomProperty<ColorWrapper>("PriceUpColor", ColorWrapper(v))

        /// Specifies the reversal amount for the chart.
        member x.ReversalAmount
            with get() = x.GetCustomProperty<string>("ReversalAmount", "3%")
            and set(v) = x.SetCustomProperty<string>("ReversalAmount", v)

        /// <summary>
        ///   Specifies the index of the Y value to use to
        ///   plot the Kagi, Renko, or Three Line Break chart, with
        ///   the first Y value at index 0.
        /// </summary>
        /// <remarks>Any positive integer 0.</remarks>
        member x.UsedYValue
            with get() = x.GetCustomProperty<int>("UsedYValue", 0)
            and set(v) = x.SetCustomProperty<int>("UsedYValue", v)


    /// Illustrates trends in data with the passing of time.
    type LineChart() = 
        inherit GenericChart<OneValue>()

        /// Returns the type of the chart series
        override x.ChartType = SeriesChartType.Line

        /// Specifies the value to be used for empty points.
        member x.EmptyPointValue
            with get() = x.GetCustomProperty<EmptyPointValue>("EmptyPointValue", EmptyPointValue.Average)
            and set(v) = x.SetCustomProperty<EmptyPointValue>("EmptyPointValue", v)

        /// Specifies the label position of the data point.
        member x.LabelStyle
            with get() = x.GetCustomProperty<LabelStyle>("LabelStyle", LabelStyle.Auto)
            and set(v) = x.SetCustomProperty<LabelStyle>("LabelStyle", v)

        /// <summary>
        ///   Specifies the 3D series depth in pixels.
        /// </summary>
        /// <remarks>Any integer &gt; 0</remarks>
        member x.PixelPointDepth
            with get() = x.GetCustomProperty<int>("PixelPointDepth", 0)
            and set(v) = x.SetCustomProperty<int>("PixelPointDepth", v)

        /// <summary>
        ///   Specifies the 3D gap depth in pixels.
        /// </summary>
        /// <remarks>Any integer &gt; 0</remarks>
        member x.PixelPointGapDepth
            with get() = x.GetCustomProperty<int>("PixelPointGapDepth", 0)
            and set(v) = x.SetCustomProperty<int>("PixelPointGapDepth", v)

        /// Specifies whether marker lines are displayed when rendered in 3D.
        member x.ShowMarkerLines
            with get() = x.GetCustomProperty<bool>("ShowMarkerLines", false)
            and set(v) = x.SetCustomProperty<bool>("ShowMarkerLines", v)


    /// Shows how proportions of data, shown as pie-shaped pieces, contribute to
    /// the data as a whole.
    type PieChart() = 
        inherit GenericChart<OneValue>()

        /// Returns the type of the chart series
        override x.ChartType = SeriesChartType.Pie

        /// <summary>
        ///   Specifies the 3D label line size as a percentage of
        ///   the default size.
        /// </summary>
        /// <remarks>Any integer from 30 to 200.</remarks>
        member x.LabelLineSize3D
            with get() = x.GetCustomProperty<int>("3DLabelLineSize", 100)
            and set(v) = x.SetCustomProperty<int>("3DLabelLineSize", v)

        /// Specifies the color of the collected pie or doughnut slice.
        member x.CollectedColor
            with get() = x.GetCustomProperty<ColorWrapper>("CollectedColor", ColorWrapper(Color.Empty)).Color
            and set(v) = x.SetCustomProperty<ColorWrapper>("CollectedColor", ColorWrapper(v))

        /// Specifies the label of the collected pie slice.
        member x.CollectedLabel
            with get() = x.GetCustomProperty<string>("CollectedLabel", "")
            and set(v) = x.SetCustomProperty<string>("CollectedLabel", v)

        /// Specifies the legend text for the collected pie slice.
        member x.CollectedLegendText
            with get() = x.GetCustomProperty<string>("CollectedLegendText", "")
            and set(v) = x.SetCustomProperty<string>("CollectedLegendText", v)

        /// Specifies whether the collected pie slice will be shown as
        /// exploded.
        member x.CollectedSliceExploded
            with get() = x.GetCustomProperty<bool>("CollectedSliceExploded", true)
            and set(v) = x.SetCustomProperty<bool>("CollectedSliceExploded", v)

        /// <summary>
        ///   Specifies the threshold value for collecting small pie slices.
        /// </summary>
        /// <remarks>Any double between 0 and 100 if CollectedThresholdUsePercent is true; otherwise, any double &gt; 0.</remarks>
        member x.CollectedThreshold
            with get() = x.GetCustomProperty<float>("CollectedThreshold", 0.0)
            and set(v) = x.SetCustomProperty<float>("CollectedThreshold", v)

        /// Specifies whether to use the collected threshold value as a
        /// percentage.
        member x.CollectedThresholdUsePercent
            with get() = x.GetCustomProperty<bool>("CollectedThresholdUsePercent", true)
            and set(v) = x.SetCustomProperty<bool>("CollectedThresholdUsePercent", v)

        /// Specifies the tooltip text of the collected pie slice.
        member x.CollectedToolTip
            with get() = x.GetCustomProperty<string>("CollectedToolTip", "")
            and set(v) = x.SetCustomProperty<string>("CollectedToolTip", v)

        /// Specifies whether the Pie or Doughnut data point is exploded.
        member x.Exploded
            with get() = x.GetCustomProperty<bool>("Exploded", false)
            and set(v) = x.SetCustomProperty<bool>("Exploded", v)

        /// <summary>
        ///   Specifies the size of the horizontal segment of the callout
        ///   line.
        /// </summary>
        /// <remarks>Any integer from 0 to 100.</remarks>
        member x.LabelsHorizontalLineSize
            with get() = x.GetCustomProperty<int>("LabelsHorizontalLineSize", 1)
            and set(v) = x.SetCustomProperty<int>("LabelsHorizontalLineSize", v)

        /// <summary>
        ///   Specifies the size of the radial segment of the callout
        ///   line.
        /// </summary>
        /// <remarks>Any integer from 0 to 100.</remarks>
        member x.LabelsRadialLineSize
            with get() = x.GetCustomProperty<int>("LabelsRadialLineSize", 1)
            and set(v) = x.SetCustomProperty<int>("LabelsRadialLineSize", v)

        /// <summary>
        ///   Specifies the minimum pie or doughnut size.
        /// </summary>
        /// <remarks>Any integer from 10 to 70.</remarks>
        member x.MinimumRelativePieSize
            with get() = x.GetCustomProperty<int>("MinimumRelativePieSize", 30)
            and set(v) = x.SetCustomProperty<int>("MinimumRelativePieSize", v)

        /// Specifies the drawing style of the data points.
        member x.PieDrawingStyle
            with get() = x.GetCustomProperty<PieDrawingStyle>("PieDrawingStyle", PieDrawingStyle.Default)
            and set(v) = x.SetCustomProperty<PieDrawingStyle>("PieDrawingStyle", v)

        /// Specifies the label style of the data points.
        member x.PieLabelStyle
            with get() = x.GetCustomProperty<PieLabelStyle>("PieLabelStyle", PieLabelStyle.Inside)
            and set(v) = x.SetCustomProperty<PieLabelStyle>("PieLabelStyle", v)

        /// Specifies the color of the radial and horizontal segments of
        /// the callout lines.
        member x.PieLineColor
            with get() = x.GetCustomProperty<ColorWrapper>("PieLineColor", ColorWrapper(Color.Black)).Color
            and set(v) = x.SetCustomProperty<ColorWrapper>("PieLineColor", ColorWrapper(v))

        /// <summary>
        ///   Specifies the angle of the data point in the Pie
        ///   or Doughnut chart.
        /// </summary>
        /// <remarks>Any integer from 0 to 360.</remarks>
        member x.PieStartAngle
            with get() = x.GetCustomProperty<int>("PieStartAngle", 90)
            and set(v) = x.SetCustomProperty<int>("PieStartAngle", v)


    /// Uses points to represent data points.
    type PointChart() = 
        inherit GenericChart<OneValue>()

        /// Returns the type of the chart series
        override x.ChartType = SeriesChartType.Point

        /// Specifies the value to be used for empty points.
        member x.EmptyPointValue
            with get() = x.GetCustomProperty<EmptyPointValue>("EmptyPointValue", EmptyPointValue.Average)
            and set(v) = x.SetCustomProperty<EmptyPointValue>("EmptyPointValue", v)

        /// Specifies the label position of the data point.
        member x.LabelStyle
            with get() = x.GetCustomProperty<LabelStyle>("LabelStyle", LabelStyle.Auto)
            and set(v) = x.SetCustomProperty<LabelStyle>("LabelStyle", v)

        /// <summary>
        ///   Specifies the 3D series depth in pixels.
        /// </summary>
        /// <remarks>Any integer &gt; 0</remarks>
        member x.PixelPointDepth
            with get() = x.GetCustomProperty<int>("PixelPointDepth", 0)
            and set(v) = x.SetCustomProperty<int>("PixelPointDepth", v)

        /// <summary>
        ///   Specifies the 3D gap depth in pixels.
        /// </summary>
        /// <remarks>Any integer &gt; 0</remarks>
        member x.PixelPointGapDepth
            with get() = x.GetCustomProperty<int>("PixelPointGapDepth", 0)
            and set(v) = x.SetCustomProperty<int>("PixelPointGapDepth", v)


    /// Disregards the passage of time and only displays changes in
    /// prices.
    type PointAndFigureChart() = 
        inherit GenericChart<TwoValue>()

        /// Returns the type of the chart series
        override x.ChartType = SeriesChartType.PointAndFigure

        /// Specifies the box size in the Renko or Point and
        /// Figure charts.
        member x.BoxSize
            with get() = x.GetCustomProperty<string>("BoxSize", "4%")
            and set(v) = x.SetCustomProperty<string>("BoxSize", v)

        /// <summary>
        ///   Specifies the 3D series depth in pixels.
        /// </summary>
        /// <remarks>Any integer &gt; 0</remarks>
        member x.PixelPointDepth
            with get() = x.GetCustomProperty<int>("PixelPointDepth", 0)
            and set(v) = x.SetCustomProperty<int>("PixelPointDepth", v)

        /// <summary>
        ///   Specifies the 3D gap depth in pixels.
        /// </summary>
        /// <remarks>Any integer &gt; 0</remarks>
        member x.PixelPointGapDepth
            with get() = x.GetCustomProperty<int>("PixelPointGapDepth", 0)
            and set(v) = x.SetCustomProperty<int>("PixelPointGapDepth", v)

        /// Specifies the data point color that indicates an increasing trend.
        member x.PriceUpColor
            with get() = x.GetCustomProperty<ColorWrapper>("PriceUpColor", ColorWrapper(Color.Empty)).Color
            and set(v) = x.SetCustomProperty<ColorWrapper>("PriceUpColor", ColorWrapper(v))

        /// Specifies whether the Point and Figure chart should draw the
        /// X and O values proportionally.
        member x.ProportionalSymbols
            with get() = x.GetCustomProperty<bool>("ProportionalSymbols", true)
            and set(v) = x.SetCustomProperty<bool>("ProportionalSymbols", v)

        /// Specifies the reversal amount for the chart.
        member x.ReversalAmount
            with get() = x.GetCustomProperty<string>("ReversalAmount", "3%")
            and set(v) = x.SetCustomProperty<string>("ReversalAmount", v)

        /// <summary>
        ///   Specifies the index of the Y value to use for
        ///   the high price in the Point and Figure chart, with
        ///   the first Y value at index 0.
        /// </summary>
        /// <remarks>Any positive integer 0.</remarks>
        member x.UsedYValueHigh
            with get() = x.GetCustomProperty<int>("UsedYValueHigh", 0)
            and set(v) = x.SetCustomProperty<int>("UsedYValueHigh", v)

        /// <summary>
        ///   Specifies the index of the Y value to use for
        ///   the low price in the Point and Figure chart, with
        ///   the first Y value at index 0.
        /// </summary>
        /// <remarks>Any positive integer 0.</remarks>
        member x.UsedYValueLow
            with get() = x.GetCustomProperty<int>("UsedYValueLow", 0)
            and set(v) = x.SetCustomProperty<int>("UsedYValueLow", v)


    /// A circular graph on which data points are displayed using
    /// the angle, and the distance from the center point.
    type PolarChart() = 
        inherit GenericChart<OneValue>()

        /// Returns the type of the chart series
        override x.ChartType = SeriesChartType.Polar

        /// Specifies the plot area shape in Radar and Polar charts.
        member x.AreaDrawingStyle
            with get() = x.GetCustomProperty<AreaDrawingStyle>("AreaDrawingStyle", AreaDrawingStyle.Circle)
            and set(v) = x.SetCustomProperty<AreaDrawingStyle>("AreaDrawingStyle", v)

        /// Specifies the text orientation of the axis labels in Radar
        /// and Polar charts.
        member x.CircularLabelStyle
            with get() = x.GetCustomProperty<CircularLabelStyle>("CircularLabelStyle", CircularLabelStyle.Horizontal)
            and set(v) = x.SetCustomProperty<CircularLabelStyle>("CircularLabelStyle", v)

        /// Specifies the value to be used for empty points.
        member x.EmptyPointValue
            with get() = x.GetCustomProperty<EmptyPointValue>("EmptyPointValue", EmptyPointValue.Average)
            and set(v) = x.SetCustomProperty<EmptyPointValue>("EmptyPointValue", v)

        /// Specifies the label position of the data point.
        member x.LabelStyle
            with get() = x.GetCustomProperty<LabelStyle>("LabelStyle", LabelStyle.Auto)
            and set(v) = x.SetCustomProperty<LabelStyle>("LabelStyle", v)

        /// Specifies the drawing style of the Polar chart type.
        member x.PolarDrawingStyle
            with get() = x.GetCustomProperty<PolarDrawingStyle>("PolarDrawingStyle", PolarDrawingStyle.Line)
            and set(v) = x.SetCustomProperty<PolarDrawingStyle>("PolarDrawingStyle", v)


    /// Displays data that, when combined, equals 100%.
    type PyramidChart() = 
        inherit GenericChart<OneValue>()

        /// Returns the type of the chart series
        override x.ChartType = SeriesChartType.Pyramid

        /// Specifies the line color of the callout for the data
        /// point labels of Funnel or Pyramid charts.
        member x.CalloutLineColor
            with get() = x.GetCustomProperty<ColorWrapper>("CalloutLineColor", ColorWrapper(Color.Empty)).Color
            and set(v) = x.SetCustomProperty<ColorWrapper>("CalloutLineColor", ColorWrapper(v))

        /// Specifies the 3D drawing style of the Pyramid chart type.
        member x.Pyramid3DDrawingStyle
            with get() = x.GetCustomProperty<Pyramid3DDrawingStyle>("Pyramid3DDrawingStyle", Pyramid3DDrawingStyle.SquareBase)
            and set(v) = x.SetCustomProperty<Pyramid3DDrawingStyle>("Pyramid3DDrawingStyle", v)

        /// <summary>
        ///   Specifies the 3D rotation angle of the Pyramid chart.
        /// </summary>
        /// <remarks>Any integer from -10 to 10.</remarks>
        member x.Pyramid3DRotationAngle
            with get() = x.GetCustomProperty<int>("Pyramid3DRotationAngle", 5)
            and set(v) = x.SetCustomProperty<int>("Pyramid3DRotationAngle", v)

        /// Specifies the placement of the data point labels in the
        /// Pyramid chart when they are placed inside the pyramid.
        member x.PyramidInsideLabelAlignment
            with get() = x.GetCustomProperty<PyramidInsideLabelAlignment>("PyramidInsideLabelAlignment", PyramidInsideLabelAlignment.Center)
            and set(v) = x.SetCustomProperty<PyramidInsideLabelAlignment>("PyramidInsideLabelAlignment", v)

        /// Specifies the style of data point labels in the Pyramid
        /// chart.
        member x.PyramidLabelStyle
            with get() = x.GetCustomProperty<PyramidLabelStyle>("PyramidLabelStyle", PyramidLabelStyle.OutsideInColumn)
            and set(v) = x.SetCustomProperty<PyramidLabelStyle>("PyramidLabelStyle", v)

        /// <summary>
        ///   Specifies the minimum height of a data point measured in
        ///   relative coordinates.
        /// </summary>
        /// <remarks>Any integer from 0 to 100.</remarks>
        member x.PyramidMinPointHeight
            with get() = x.GetCustomProperty<int>("PyramidMinPointHeight", 0)
            and set(v) = x.SetCustomProperty<int>("PyramidMinPointHeight", v)

        /// Specifies the placement of the data point labels in the
        /// Pyramid chart when the labels are placed outside the pyramid.
        member x.PyramidOutsideLabelPlacement
            with get() = x.GetCustomProperty<PyramidOutsideLabelPlacement>("PyramidOutsideLabelPlacement", PyramidOutsideLabelPlacement.Right)
            and set(v) = x.SetCustomProperty<PyramidOutsideLabelPlacement>("PyramidOutsideLabelPlacement", v)

        /// <summary>
        ///   Specifies the gap size between the data points, measured in
        ///   relative coordinates.
        /// </summary>
        /// <remarks>Any integer from 0 to 100.</remarks>
        member x.PyramidPointGap
            with get() = x.GetCustomProperty<int>("PyramidPointGap", 0)
            and set(v) = x.SetCustomProperty<int>("PyramidPointGap", v)

        /// Specifies whether the data point value represents a linear height
        /// or the surface of the segment.
        member x.PyramidValueType
            with get() = x.GetCustomProperty<PyramidValueType>("PyramidValueType", PyramidValueType.Linear)
            and set(v) = x.SetCustomProperty<PyramidValueType>("PyramidValueType", v)


    /// A circular chart that is used primarily as a data
    /// comparison tool.
    type RadarChart() = 
        inherit GenericChart<OneValue>()

        /// Returns the type of the chart series
        override x.ChartType = SeriesChartType.Radar

        /// Specifies the plot area shape in Radar and Polar charts.
        member x.AreaDrawingStyle
            with get() = x.GetCustomProperty<AreaDrawingStyle>("AreaDrawingStyle", AreaDrawingStyle.Circle)
            and set(v) = x.SetCustomProperty<AreaDrawingStyle>("AreaDrawingStyle", v)

        /// Specifies the text orientation of the axis labels in Radar
        /// and Polar charts.
        member x.CircularLabelStyle
            with get() = x.GetCustomProperty<CircularLabelStyle>("CircularLabelStyle", CircularLabelStyle.Horizontal)
            and set(v) = x.SetCustomProperty<CircularLabelStyle>("CircularLabelStyle", v)

        /// Specifies the value to be used for empty points.
        member x.EmptyPointValue
            with get() = x.GetCustomProperty<EmptyPointValue>("EmptyPointValue", EmptyPointValue.Average)
            and set(v) = x.SetCustomProperty<EmptyPointValue>("EmptyPointValue", v)

        /// Specifies the label position of the data point.
        member x.LabelStyle
            with get() = x.GetCustomProperty<LabelStyle>("LabelStyle", LabelStyle.Auto)
            and set(v) = x.SetCustomProperty<LabelStyle>("LabelStyle", v)

        /// Specifies the drawing style of the Radar chart.
        member x.RadarDrawingStyle
            with get() = x.GetCustomProperty<RadarDrawingStyle>("RadarDrawingStyle", RadarDrawingStyle.Area)
            and set(v) = x.SetCustomProperty<RadarDrawingStyle>("RadarDrawingStyle", v)


    /// Displays a range of data by plotting two Y values per data
    /// point, with each Y value being drawn as a line
    /// chart.
    type RangeChart() = 
        inherit GenericChart<TwoValue>()

        /// Returns the type of the chart series
        override x.ChartType = SeriesChartType.Range

        /// Specifies the value to be used for empty points.
        member x.EmptyPointValue
            with get() = x.GetCustomProperty<EmptyPointValue>("EmptyPointValue", EmptyPointValue.Average)
            and set(v) = x.SetCustomProperty<EmptyPointValue>("EmptyPointValue", v)

        /// Specifies the label position of the data point.
        member x.LabelStyle
            with get() = x.GetCustomProperty<LabelStyle>("LabelStyle", LabelStyle.Auto)
            and set(v) = x.SetCustomProperty<LabelStyle>("LabelStyle", v)

        /// <summary>
        ///   Specifies the 3D series depth in pixels.
        /// </summary>
        /// <remarks>Any integer &gt; 0</remarks>
        member x.PixelPointDepth
            with get() = x.GetCustomProperty<int>("PixelPointDepth", 0)
            and set(v) = x.SetCustomProperty<int>("PixelPointDepth", v)

        /// <summary>
        ///   Specifies the 3D gap depth in pixels.
        /// </summary>
        /// <remarks>Any integer &gt; 0</remarks>
        member x.PixelPointGapDepth
            with get() = x.GetCustomProperty<int>("PixelPointGapDepth", 0)
            and set(v) = x.SetCustomProperty<int>("PixelPointGapDepth", v)

        /// Specifies whether marker lines are displayed when rendered in 3D.
        member x.ShowMarkerLines
            with get() = x.GetCustomProperty<bool>("ShowMarkerLines", false)
            and set(v) = x.SetCustomProperty<bool>("ShowMarkerLines", v)


    /// Displays separate events that have beginning and end values.
    type RangeBarChart() = 
        inherit GenericChart<TwoValue>()

        /// Returns the type of the chart series
        override x.ChartType = SeriesChartType.RangeBar

        /// Specifies the placement of the data point label.
        member x.BarLabelStyle
            with get() = x.GetCustomProperty<BarLabelStyle>("BarLabelStyle", BarLabelStyle.Outside)
            and set(v) = x.SetCustomProperty<BarLabelStyle>("BarLabelStyle", v)

        /// Specifies the drawing style of data points.
        member x.DrawingStyle
            with get() = x.GetCustomProperty<DrawingStyle>("DrawingStyle", DrawingStyle.Default)
            and set(v) = x.SetCustomProperty<DrawingStyle>("DrawingStyle", v)

        /// Specifies whether series of the same chart type are drawn
        /// next to each other instead of overlapping each other.
        member x.DrawSideBySide
            with get() = x.GetCustomProperty<DrawSideBySide>("DrawSideBySide", DrawSideBySide.Auto)
            and set(v) = x.SetCustomProperty<DrawSideBySide>("DrawSideBySide", v)

        /// Specifies the value to be used for empty points.
        member x.EmptyPointValue
            with get() = x.GetCustomProperty<EmptyPointValue>("EmptyPointValue", EmptyPointValue.Average)
            and set(v) = x.SetCustomProperty<EmptyPointValue>("EmptyPointValue", v)

        /// <summary>
        ///   Specifies the maximum width of the data point in pixels.
        /// </summary>
        /// <remarks>Any integer &gt; 0</remarks>
        member x.MaxPixelPointWidth
            with get() = x.GetCustomProperty<int>("MaxPixelPointWidth", 0)
            and set(v) = x.SetCustomProperty<int>("MaxPixelPointWidth", v)

        /// <summary>
        ///   Specifies the minimum data point width in pixels.
        /// </summary>
        /// <remarks>Any integer &gt; 0</remarks>
        member x.MinPixelPointWidth
            with get() = x.GetCustomProperty<int>("MinPixelPointWidth", 0)
            and set(v) = x.SetCustomProperty<int>("MinPixelPointWidth", v)

        /// <summary>
        ///   Specifies the 3D series depth in pixels.
        /// </summary>
        /// <remarks>Any integer &gt; 0</remarks>
        member x.PixelPointDepth
            with get() = x.GetCustomProperty<int>("PixelPointDepth", 0)
            and set(v) = x.SetCustomProperty<int>("PixelPointDepth", v)

        /// <summary>
        ///   Specifies the 3D gap depth in pixels.
        /// </summary>
        /// <remarks>Any integer &gt; 0</remarks>
        member x.PixelPointGapDepth
            with get() = x.GetCustomProperty<int>("PixelPointGapDepth", 0)
            and set(v) = x.SetCustomProperty<int>("PixelPointGapDepth", v)

        /// <summary>
        ///   Specifies the data point width in pixels.
        /// </summary>
        /// <remarks>Any integer &gt; 0</remarks>
        member x.PixelPointWidth
            with get() = x.GetCustomProperty<int>("PixelPointWidth", 0)
            and set(v) = x.SetCustomProperty<int>("PixelPointWidth", v)

        /// <summary>
        ///   Specifies the relative data point width.
        /// </summary>
        /// <remarks>Any double from 0 to 2.</remarks>
        member x.PointWidth
            with get() = x.GetCustomProperty<float>("PointWidth", 0.8)
            and set(v) = x.SetCustomProperty<float>("PointWidth", v)


    /// Displays a range of data by plotting two Y values
    /// per data point.
    type RangeColumnChart() = 
        inherit GenericChart<TwoValue>()

        /// Returns the type of the chart series
        override x.ChartType = SeriesChartType.RangeColumn

        /// Specifies the drawing style of data points.
        member x.DrawingStyle
            with get() = x.GetCustomProperty<DrawingStyle>("DrawingStyle", DrawingStyle.Default)
            and set(v) = x.SetCustomProperty<DrawingStyle>("DrawingStyle", v)

        /// Specifies whether series of the same chart type are drawn
        /// next to each other instead of overlapping each other.
        member x.DrawSideBySide
            with get() = x.GetCustomProperty<DrawSideBySide>("DrawSideBySide", DrawSideBySide.Auto)
            and set(v) = x.SetCustomProperty<DrawSideBySide>("DrawSideBySide", v)

        /// Specifies the value to be used for empty points.
        member x.EmptyPointValue
            with get() = x.GetCustomProperty<EmptyPointValue>("EmptyPointValue", EmptyPointValue.Average)
            and set(v) = x.SetCustomProperty<EmptyPointValue>("EmptyPointValue", v)

        /// <summary>
        ///   Specifies the maximum width of the data point in pixels.
        /// </summary>
        /// <remarks>Any integer &gt; 0</remarks>
        member x.MaxPixelPointWidth
            with get() = x.GetCustomProperty<int>("MaxPixelPointWidth", 0)
            and set(v) = x.SetCustomProperty<int>("MaxPixelPointWidth", v)

        /// <summary>
        ///   Specifies the minimum data point width in pixels.
        /// </summary>
        /// <remarks>Any integer &gt; 0</remarks>
        member x.MinPixelPointWidth
            with get() = x.GetCustomProperty<int>("MinPixelPointWidth", 0)
            and set(v) = x.SetCustomProperty<int>("MinPixelPointWidth", v)

        /// <summary>
        ///   Specifies the 3D series depth in pixels.
        /// </summary>
        /// <remarks>Any integer &gt; 0</remarks>
        member x.PixelPointDepth
            with get() = x.GetCustomProperty<int>("PixelPointDepth", 0)
            and set(v) = x.SetCustomProperty<int>("PixelPointDepth", v)

        /// <summary>
        ///   Specifies the 3D gap depth in pixels.
        /// </summary>
        /// <remarks>Any integer &gt; 0</remarks>
        member x.PixelPointGapDepth
            with get() = x.GetCustomProperty<int>("PixelPointGapDepth", 0)
            and set(v) = x.SetCustomProperty<int>("PixelPointGapDepth", v)

        /// <summary>
        ///   Specifies the data point width in pixels.
        /// </summary>
        /// <remarks>Any integer &gt; 0</remarks>
        member x.PixelPointWidth
            with get() = x.GetCustomProperty<int>("PixelPointWidth", 0)
            and set(v) = x.SetCustomProperty<int>("PixelPointWidth", v)

        /// <summary>
        ///   Specifies the relative data point width.
        /// </summary>
        /// <remarks>Any double from 0 to 2.</remarks>
        member x.PointWidth
            with get() = x.GetCustomProperty<float>("PointWidth", 0.8)
            and set(v) = x.SetCustomProperty<float>("PointWidth", v)


    /// Displays a series of connecting vertical lines where the thickness
    /// and direction of the lines are dependent on the action
    /// of the price value.
    type RenkoChart() = 
        inherit GenericChart<OneValue>()

        /// Returns the type of the chart series
        override x.ChartType = SeriesChartType.Renko

        /// Specifies the box size in the Renko or Point and
        /// Figure charts.
        member x.BoxSize
            with get() = x.GetCustomProperty<string>("BoxSize", "4%")
            and set(v) = x.SetCustomProperty<string>("BoxSize", v)

        /// <summary>
        ///   Specifies the 3D series depth in pixels.
        /// </summary>
        /// <remarks>Any integer &gt; 0</remarks>
        member x.PixelPointDepth
            with get() = x.GetCustomProperty<int>("PixelPointDepth", 0)
            and set(v) = x.SetCustomProperty<int>("PixelPointDepth", v)

        /// <summary>
        ///   Specifies the 3D gap depth in pixels.
        /// </summary>
        /// <remarks>Any integer &gt; 0</remarks>
        member x.PixelPointGapDepth
            with get() = x.GetCustomProperty<int>("PixelPointGapDepth", 0)
            and set(v) = x.SetCustomProperty<int>("PixelPointGapDepth", v)

        /// Specifies the data point color that indicates an increasing trend.
        member x.PriceUpColor
            with get() = x.GetCustomProperty<ColorWrapper>("PriceUpColor", ColorWrapper(Color.Empty)).Color
            and set(v) = x.SetCustomProperty<ColorWrapper>("PriceUpColor", ColorWrapper(v))

        /// <summary>
        ///   Specifies the index of the Y value to use to
        ///   plot the Kagi, Renko, or Three Line Break chart, with
        ///   the first Y value at index 0.
        /// </summary>
        /// <remarks>Any positive integer 0.</remarks>
        member x.UsedYValue
            with get() = x.GetCustomProperty<int>("UsedYValue", 0)
            and set(v) = x.SetCustomProperty<int>("UsedYValue", v)


    /// A Line chart that plots a fitted curve through each
    /// data point in a series.
    type SplineChart() = 
        inherit GenericChart<OneValue>()

        /// Returns the type of the chart series
        override x.ChartType = SeriesChartType.Spline

        /// Specifies the value to be used for empty points.
        member x.EmptyPointValue
            with get() = x.GetCustomProperty<EmptyPointValue>("EmptyPointValue", EmptyPointValue.Average)
            and set(v) = x.SetCustomProperty<EmptyPointValue>("EmptyPointValue", v)

        /// Specifies the label position of the data point.
        member x.LabelStyle
            with get() = x.GetCustomProperty<LabelStyle>("LabelStyle", LabelStyle.Auto)
            and set(v) = x.SetCustomProperty<LabelStyle>("LabelStyle", v)

        /// <summary>
        ///   Specifies the line tension for the drawing of curves between
        ///   data points.
        /// </summary>
        /// <remarks>Any double from 0 to 2.</remarks>
        member x.LineTension
            with get() = x.GetCustomProperty<float>("LineTension", 0.8)
            and set(v) = x.SetCustomProperty<float>("LineTension", v)

        /// <summary>
        ///   Specifies the 3D series depth in pixels.
        /// </summary>
        /// <remarks>Any integer &gt; 0</remarks>
        member x.PixelPointDepth
            with get() = x.GetCustomProperty<int>("PixelPointDepth", 0)
            and set(v) = x.SetCustomProperty<int>("PixelPointDepth", v)

        /// <summary>
        ///   Specifies the 3D gap depth in pixels.
        /// </summary>
        /// <remarks>Any integer &gt; 0</remarks>
        member x.PixelPointGapDepth
            with get() = x.GetCustomProperty<int>("PixelPointGapDepth", 0)
            and set(v) = x.SetCustomProperty<int>("PixelPointGapDepth", v)

        /// Specifies whether marker lines are displayed when rendered in 3D.
        member x.ShowMarkerLines
            with get() = x.GetCustomProperty<bool>("ShowMarkerLines", false)
            and set(v) = x.SetCustomProperty<bool>("ShowMarkerLines", v)


    /// An Area chart that plots a fitted curve through each
    /// data point in a series.
    type SplineAreaChart() = 
        inherit GenericChart<OneValue>()

        /// Returns the type of the chart series
        override x.ChartType = SeriesChartType.SplineArea

        /// Specifies the value to be used for empty points.
        member x.EmptyPointValue
            with get() = x.GetCustomProperty<EmptyPointValue>("EmptyPointValue", EmptyPointValue.Average)
            and set(v) = x.SetCustomProperty<EmptyPointValue>("EmptyPointValue", v)

        /// Specifies the label position of the data point.
        member x.LabelStyle
            with get() = x.GetCustomProperty<LabelStyle>("LabelStyle", LabelStyle.Auto)
            and set(v) = x.SetCustomProperty<LabelStyle>("LabelStyle", v)

        /// <summary>
        ///   Specifies the line tension for the drawing of curves between
        ///   data points.
        /// </summary>
        /// <remarks>Any double from 0 to 2.</remarks>
        member x.LineTension
            with get() = x.GetCustomProperty<float>("LineTension", 0.8)
            and set(v) = x.SetCustomProperty<float>("LineTension", v)

        /// <summary>
        ///   Specifies the 3D series depth in pixels.
        /// </summary>
        /// <remarks>Any integer &gt; 0</remarks>
        member x.PixelPointDepth
            with get() = x.GetCustomProperty<int>("PixelPointDepth", 0)
            and set(v) = x.SetCustomProperty<int>("PixelPointDepth", v)

        /// <summary>
        ///   Specifies the 3D gap depth in pixels.
        /// </summary>
        /// <remarks>Any integer &gt; 0</remarks>
        member x.PixelPointGapDepth
            with get() = x.GetCustomProperty<int>("PixelPointGapDepth", 0)
            and set(v) = x.SetCustomProperty<int>("PixelPointGapDepth", v)

        /// Specifies whether marker lines are displayed when rendered in 3D.
        member x.ShowMarkerLines
            with get() = x.GetCustomProperty<bool>("ShowMarkerLines", false)
            and set(v) = x.SetCustomProperty<bool>("ShowMarkerLines", v)


    /// Displays a range of data by plotting two Y values per
    /// data point, with each Y value drawn as a line
    /// chart.
    type SplineRangeChart() = 
        inherit GenericChart<TwoValue>()

        /// Returns the type of the chart series
        override x.ChartType = SeriesChartType.SplineRange

        /// Specifies the value to be used for empty points.
        member x.EmptyPointValue
            with get() = x.GetCustomProperty<EmptyPointValue>("EmptyPointValue", EmptyPointValue.Average)
            and set(v) = x.SetCustomProperty<EmptyPointValue>("EmptyPointValue", v)

        /// Specifies the label position of the data point.
        member x.LabelStyle
            with get() = x.GetCustomProperty<LabelStyle>("LabelStyle", LabelStyle.Auto)
            and set(v) = x.SetCustomProperty<LabelStyle>("LabelStyle", v)

        /// <summary>
        ///   Specifies the line tension for the drawing of curves between
        ///   data points.
        /// </summary>
        /// <remarks>Any double from 0 to 2.</remarks>
        member x.LineTension
            with get() = x.GetCustomProperty<float>("LineTension", 0.8)
            and set(v) = x.SetCustomProperty<float>("LineTension", v)

        /// <summary>
        ///   Specifies the 3D series depth in pixels.
        /// </summary>
        /// <remarks>Any integer &gt; 0</remarks>
        member x.PixelPointDepth
            with get() = x.GetCustomProperty<int>("PixelPointDepth", 0)
            and set(v) = x.SetCustomProperty<int>("PixelPointDepth", v)

        /// <summary>
        ///   Specifies the 3D gap depth in pixels.
        /// </summary>
        /// <remarks>Any integer &gt; 0</remarks>
        member x.PixelPointGapDepth
            with get() = x.GetCustomProperty<int>("PixelPointGapDepth", 0)
            and set(v) = x.SetCustomProperty<int>("PixelPointGapDepth", v)

        /// Specifies whether marker lines are displayed when rendered in 3D.
        member x.ShowMarkerLines
            with get() = x.GetCustomProperty<bool>("ShowMarkerLines", false)
            and set(v) = x.SetCustomProperty<bool>("ShowMarkerLines", v)


    /// An Area chart that stacks two or more data series
    /// on top of one another.
    type StackedAreaChart() = 
        inherit GenericChart<OneValue>()

        /// Returns the type of the chart series
        override x.ChartType = SeriesChartType.StackedArea

        /// <summary>
        ///   Specifies the 3D series depth in pixels.
        /// </summary>
        /// <remarks>Any integer &gt; 0</remarks>
        member x.PixelPointDepth
            with get() = x.GetCustomProperty<int>("PixelPointDepth", 0)
            and set(v) = x.SetCustomProperty<int>("PixelPointDepth", v)

        /// <summary>
        ///   Specifies the 3D gap depth in pixels.
        /// </summary>
        /// <remarks>Any integer &gt; 0</remarks>
        member x.PixelPointGapDepth
            with get() = x.GetCustomProperty<int>("PixelPointGapDepth", 0)
            and set(v) = x.SetCustomProperty<int>("PixelPointGapDepth", v)


    /// Displays series of the same chart type as stacked bars.
    type StackedBarChart() = 
        inherit GenericChart<OneValue>()

        /// Returns the type of the chart series
        override x.ChartType = SeriesChartType.StackedBar

        /// Specifies the placement of the data point label.
        member x.BarLabelStyle
            with get() = x.GetCustomProperty<BarLabelStyle>("BarLabelStyle", BarLabelStyle.Outside)
            and set(v) = x.SetCustomProperty<BarLabelStyle>("BarLabelStyle", v)

        /// Specifies the drawing style of data points.
        member x.DrawingStyle
            with get() = x.GetCustomProperty<DrawingStyle>("DrawingStyle", DrawingStyle.Default)
            and set(v) = x.SetCustomProperty<DrawingStyle>("DrawingStyle", v)

        /// <summary>
        ///   Specifies the maximum width of the data point in pixels.
        /// </summary>
        /// <remarks>Any integer &gt; 0</remarks>
        member x.MaxPixelPointWidth
            with get() = x.GetCustomProperty<int>("MaxPixelPointWidth", 0)
            and set(v) = x.SetCustomProperty<int>("MaxPixelPointWidth", v)

        /// <summary>
        ///   Specifies the minimum data point width in pixels.
        /// </summary>
        /// <remarks>Any integer &gt; 0</remarks>
        member x.MinPixelPointWidth
            with get() = x.GetCustomProperty<int>("MinPixelPointWidth", 0)
            and set(v) = x.SetCustomProperty<int>("MinPixelPointWidth", v)

        /// <summary>
        ///   Specifies the 3D series depth in pixels.
        /// </summary>
        /// <remarks>Any integer &gt; 0</remarks>
        member x.PixelPointDepth
            with get() = x.GetCustomProperty<int>("PixelPointDepth", 0)
            and set(v) = x.SetCustomProperty<int>("PixelPointDepth", v)

        /// <summary>
        ///   Specifies the 3D gap depth in pixels.
        /// </summary>
        /// <remarks>Any integer &gt; 0</remarks>
        member x.PixelPointGapDepth
            with get() = x.GetCustomProperty<int>("PixelPointGapDepth", 0)
            and set(v) = x.SetCustomProperty<int>("PixelPointGapDepth", v)

        /// <summary>
        ///   Specifies the data point width in pixels.
        /// </summary>
        /// <remarks>Any integer &gt; 0</remarks>
        member x.PixelPointWidth
            with get() = x.GetCustomProperty<int>("PixelPointWidth", 0)
            and set(v) = x.SetCustomProperty<int>("PixelPointWidth", v)

        /// <summary>
        ///   Specifies the relative data point width.
        /// </summary>
        /// <remarks>Any double from 0 to 2.</remarks>
        member x.PointWidth
            with get() = x.GetCustomProperty<float>("PointWidth", 0.8)
            and set(v) = x.SetCustomProperty<float>("PointWidth", v)

        /// Specifies the name of the stacked group.
        member x.StackedGroupName
            with get() = x.GetCustomProperty<string>("StackedGroupName", "")
            and set(v) = x.SetCustomProperty<string>("StackedGroupName", v)


    /// Used to compare the contribution of each value to a
    /// total across categories.
    type StackedColumnChart() = 
        inherit GenericChart<OneValue>()

        /// Returns the type of the chart series
        override x.ChartType = SeriesChartType.StackedColumn

        /// Specifies the drawing style of data points.
        member x.DrawingStyle
            with get() = x.GetCustomProperty<DrawingStyle>("DrawingStyle", DrawingStyle.Default)
            and set(v) = x.SetCustomProperty<DrawingStyle>("DrawingStyle", v)

        /// <summary>
        ///   Specifies the maximum width of the data point in pixels.
        /// </summary>
        /// <remarks>Any integer &gt; 0</remarks>
        member x.MaxPixelPointWidth
            with get() = x.GetCustomProperty<int>("MaxPixelPointWidth", 0)
            and set(v) = x.SetCustomProperty<int>("MaxPixelPointWidth", v)

        /// <summary>
        ///   Specifies the minimum data point width in pixels.
        /// </summary>
        /// <remarks>Any integer &gt; 0</remarks>
        member x.MinPixelPointWidth
            with get() = x.GetCustomProperty<int>("MinPixelPointWidth", 0)
            and set(v) = x.SetCustomProperty<int>("MinPixelPointWidth", v)

        /// <summary>
        ///   Specifies the 3D series depth in pixels.
        /// </summary>
        /// <remarks>Any integer &gt; 0</remarks>
        member x.PixelPointDepth
            with get() = x.GetCustomProperty<int>("PixelPointDepth", 0)
            and set(v) = x.SetCustomProperty<int>("PixelPointDepth", v)

        /// <summary>
        ///   Specifies the 3D gap depth in pixels.
        /// </summary>
        /// <remarks>Any integer &gt; 0</remarks>
        member x.PixelPointGapDepth
            with get() = x.GetCustomProperty<int>("PixelPointGapDepth", 0)
            and set(v) = x.SetCustomProperty<int>("PixelPointGapDepth", v)

        /// <summary>
        ///   Specifies the data point width in pixels.
        /// </summary>
        /// <remarks>Any integer &gt; 0</remarks>
        member x.PixelPointWidth
            with get() = x.GetCustomProperty<int>("PixelPointWidth", 0)
            and set(v) = x.SetCustomProperty<int>("PixelPointWidth", v)

        /// <summary>
        ///   Specifies the relative data point width.
        /// </summary>
        /// <remarks>Any double from 0 to 2.</remarks>
        member x.PointWidth
            with get() = x.GetCustomProperty<float>("PointWidth", 0.8)
            and set(v) = x.SetCustomProperty<float>("PointWidth", v)

        /// Specifies the name of the stacked group.
        member x.StackedGroupName
            with get() = x.GetCustomProperty<string>("StackedGroupName", "")
            and set(v) = x.SetCustomProperty<string>("StackedGroupName", v)


    /// Similar to the Line chart type, but uses vertical and
    /// horizontal lines to connect the data points in a series
    /// forming a step-like progression.
    type StepLineChart() = 
        inherit GenericChart<OneValue>()

        /// Returns the type of the chart series
        override x.ChartType = SeriesChartType.StepLine

        /// Specifies the value to be used for empty points.
        member x.EmptyPointValue
            with get() = x.GetCustomProperty<EmptyPointValue>("EmptyPointValue", EmptyPointValue.Average)
            and set(v) = x.SetCustomProperty<EmptyPointValue>("EmptyPointValue", v)

        /// Specifies the label position of the data point.
        member x.LabelStyle
            with get() = x.GetCustomProperty<LabelStyle>("LabelStyle", LabelStyle.Auto)
            and set(v) = x.SetCustomProperty<LabelStyle>("LabelStyle", v)

        /// <summary>
        ///   Specifies the 3D series depth in pixels.
        /// </summary>
        /// <remarks>Any integer &gt; 0</remarks>
        member x.PixelPointDepth
            with get() = x.GetCustomProperty<int>("PixelPointDepth", 0)
            and set(v) = x.SetCustomProperty<int>("PixelPointDepth", v)

        /// <summary>
        ///   Specifies the 3D gap depth in pixels.
        /// </summary>
        /// <remarks>Any integer &gt; 0</remarks>
        member x.PixelPointGapDepth
            with get() = x.GetCustomProperty<int>("PixelPointGapDepth", 0)
            and set(v) = x.SetCustomProperty<int>("PixelPointGapDepth", v)

        /// Specifies whether marker lines are displayed when rendered in 3D.
        member x.ShowMarkerLines
            with get() = x.GetCustomProperty<bool>("ShowMarkerLines", false)
            and set(v) = x.SetCustomProperty<bool>("ShowMarkerLines", v)


    /// Displays significant stock price points including the open, close, high,
    /// and low price points.
    type StockChart() = 
        inherit GenericChart<FourValue>()

        /// Returns the type of the chart series
        override x.ChartType = SeriesChartType.Stock

        /// Specifies the Y value to use as the data point
        /// label.
        member x.LabelValueType
            with get() = x.GetCustomProperty<LabelValueType>("LabelValueType", LabelValueType.Close)
            and set(v) = x.SetCustomProperty<LabelValueType>("LabelValueType", v)

        /// <summary>
        ///   Specifies the maximum width of the data point in pixels.
        /// </summary>
        /// <remarks>Any integer &gt; 0</remarks>
        member x.MaxPixelPointWidth
            with get() = x.GetCustomProperty<int>("MaxPixelPointWidth", 0)
            and set(v) = x.SetCustomProperty<int>("MaxPixelPointWidth", v)

        /// <summary>
        ///   Specifies the minimum data point width in pixels.
        /// </summary>
        /// <remarks>Any integer &gt; 0</remarks>
        member x.MinPixelPointWidth
            with get() = x.GetCustomProperty<int>("MinPixelPointWidth", 0)
            and set(v) = x.SetCustomProperty<int>("MinPixelPointWidth", v)

        /// Specifies the marker style for open and close values.
        member x.OpenCloseStyle
            with get() = x.GetCustomProperty<OpenCloseStyle>("OpenCloseStyle", OpenCloseStyle.Line)
            and set(v) = x.SetCustomProperty<OpenCloseStyle>("OpenCloseStyle", v)

        /// <summary>
        ///   Specifies the 3D series depth in pixels.
        /// </summary>
        /// <remarks>Any integer &gt; 0</remarks>
        member x.PixelPointDepth
            with get() = x.GetCustomProperty<int>("PixelPointDepth", 0)
            and set(v) = x.SetCustomProperty<int>("PixelPointDepth", v)

        /// <summary>
        ///   Specifies the 3D gap depth in pixels.
        /// </summary>
        /// <remarks>Any integer &gt; 0</remarks>
        member x.PixelPointGapDepth
            with get() = x.GetCustomProperty<int>("PixelPointGapDepth", 0)
            and set(v) = x.SetCustomProperty<int>("PixelPointGapDepth", v)

        /// <summary>
        ///   Specifies the data point width in pixels.
        /// </summary>
        /// <remarks>Any integer &gt; 0</remarks>
        member x.PixelPointWidth
            with get() = x.GetCustomProperty<int>("PixelPointWidth", 0)
            and set(v) = x.SetCustomProperty<int>("PixelPointWidth", v)

        /// <summary>
        ///   Specifies the relative data point width.
        /// </summary>
        /// <remarks>Any double from 0 to 2.</remarks>
        member x.PointWidth
            with get() = x.GetCustomProperty<float>("PointWidth", 0.8)
            and set(v) = x.SetCustomProperty<float>("PointWidth", v)

        /// Specifies whether markers for open and close prices are displayed.
        member x.ShowOpenClose
            with get() = x.GetCustomProperty<ShowOpenClose>("ShowOpenClose", ShowOpenClose.Both)
            and set(v) = x.SetCustomProperty<ShowOpenClose>("ShowOpenClose", v)


    /// Displays a series of vertical boxes, or lines, that reflect
    /// changes in price values.
    type ThreeLineBreakChart() = 
        inherit GenericChart<OneValue>()

        /// Returns the type of the chart series
        override x.ChartType = SeriesChartType.ThreeLineBreak

        /// <summary>
        ///   Specifies the number of lines to use in a Three
        ///   Line Break chart.
        /// </summary>
        /// <remarks>Any integer &gt; 0</remarks>
        member x.NumberOfLinesInBreak
            with get() = x.GetCustomProperty<int>("NumberOfLinesInBreak", 3)
            and set(v) = x.SetCustomProperty<int>("NumberOfLinesInBreak", v)

        /// <summary>
        ///   Specifies the 3D series depth in pixels.
        /// </summary>
        /// <remarks>Any integer &gt; 0</remarks>
        member x.PixelPointDepth
            with get() = x.GetCustomProperty<int>("PixelPointDepth", 0)
            and set(v) = x.SetCustomProperty<int>("PixelPointDepth", v)

        /// <summary>
        ///   Specifies the 3D gap depth in pixels.
        /// </summary>
        /// <remarks>Any integer &gt; 0</remarks>
        member x.PixelPointGapDepth
            with get() = x.GetCustomProperty<int>("PixelPointGapDepth", 0)
            and set(v) = x.SetCustomProperty<int>("PixelPointGapDepth", v)

        /// Specifies the data point color that indicates an increasing trend.
        member x.PriceUpColor
            with get() = x.GetCustomProperty<ColorWrapper>("PriceUpColor", ColorWrapper(Color.Empty)).Color
            and set(v) = x.SetCustomProperty<ColorWrapper>("PriceUpColor", ColorWrapper(v))

        /// <summary>
        ///   Specifies the index of the Y value to use to
        ///   plot the Kagi, Renko, or Three Line Break chart, with
        ///   the first Y value at index 0.
        /// </summary>
        /// <remarks>Any positive integer 0.</remarks>
        member x.UsedYValue
            with get() = x.GetCustomProperty<int>("UsedYValue", 0)
            and set(v) = x.SetCustomProperty<int>("UsedYValue", v)

    // [/AUTOGENERATED]
    // ------------------------------------------------------------------------------------
    // Special types of charts - combine multiple series & create row/columns

    type CombinedChart(charts:seq<GenericChart>) as this =
        inherit GenericChart<DataSourceCombined>()

        do
            let firstChart = Seq.head charts
            this.Area <- firstChart.Area
            this.Legend <- firstChart.Legend
            this.Margin <- firstChart.Margin

        override x.ChartType = enum<SeriesChartType> -1
        member x.Charts = charts

    type SubplotChart(charts:seq<GenericChart>, orientation:Orientation) = 
        inherit GenericChart<DataSourceCombined>()
        let r = 1.0 / (charts |> Seq.length |> float)
        let mutable splitSizes = seq { for c in charts -> r }

        override x.ChartType = enum<SeriesChartType> -1
        member x.SplitSizes with get() = splitSizes and set v = splitSizes <- v
        member x.Orientation = orientation
        member x.Charts = charts

// ----------------------------------- 
// Charting.ChartControl.fs
// ----------------------------------- 
open ChartFormUtilities
open ChartData.Internal
open ChartData
open ChartStyles
open ChartTypes

type ChartControl(ch:GenericChart) as self = 
    inherit UserControl()

    let seriesCounter = createCounter()
    let areaCounter = createCounter()
    let legendCounter = createCounter()

    let createTitleChange (chart:Chart) (ch:GenericChart) = 
        ch.TitleChanged.Add(function 
                t ->
                if (chart.Titles.Count > 0) then
                    chart.Titles.[0] <- t
                else
                    chart.Titles.Add t)

    let createLegendChange (chart:Chart) (ch:GenericChart) (series:Series list) = 
        ch.LegendChanged.Add(function 
                l ->
                if (chart.Legends.Count > 0) then
                    chart.Legends.[0] <- l
                else
                    chart.Legends.Add l
                if (chart.ChartAreas.Count > 0) then l.DockedToChartArea <- chart.ChartAreas.[0].Name
                for s in series do (s:Series).Legend <- l.Name)

    let createArea (chart:Chart) (ch:GenericChart) ((left, top, right, bottom) as pos) = 

        let setMargin (area:ChartArea) ((left, top, right, bottom) as pos) = 
            area.Position.X <- left
            area.Position.Y <- top 
            area.Position.Width <- right - left
            area.Position.Height <- bottom - top 

        let area = new ChartArea()
        applyPropertyDefaults (ch.ChartType) area
        chart.ChartAreas.Add area

        if ch.LazyArea.IsValueCreated then
            applyProperties area ch.Area
            if (ch.Area.Area3DStyle.Enable3D) then
                applyProperties area.Area3DStyle ch.Area.Area3DStyle

        area.Name <- 
            if ch.LazyArea.IsValueCreated && not (String.IsNullOrEmpty ch.Area.Name) 
            then ch.Area.Name else sprintf "Area_%d" (areaCounter())
        ch.NameChanged.Add(function
            n ->
                area.Name <- 
                    if not (String.IsNullOrEmpty n) 
                    then n else sprintf "Area_%d" (areaCounter()))

        setMargin area pos
        ch.MarginChanged.Add(function
            a ->                
                let (l, t, r, b) = (0.0f, 0.0f, 100.0f, 100.0f)
                let (ml, mt, mr, mb) = a
                let (l, t, r, b) = (l + ml, t + mt, r - mr, b - mb)
                setMargin area (l, t, r, b))


        let processTitles (ch:GenericChart) =
            for title in seq { if ch.LazyTitle.IsValueCreated then yield ch.Title 
                               yield! ch.Titles } do
                chart.Titles.Add title
            createTitleChange chart ch
    
        let processSeries (ch:GenericChart) =
            let name = 
                if not (String.IsNullOrEmpty ch.Name) then ch.Name
                else sprintf "GenericChart_Series_%d" (seriesCounter())
            let series = new Series()
            applyPropertyDefaults (ch.ChartType) series
            if ch.LazySeries.IsValueCreated then
                applyProperties series ch.Series

            series.Name <- name
            series.ChartType <- ch.ChartType
            series.ChartArea <- area.Name
            chart.Series.Add series
            
            // Set data
            setSeriesData false series ch.Data chart ch.SetCustomProperty

            let cult = System.Threading.Thread.CurrentThread.CurrentCulture
            System.Threading.Thread.CurrentThread.CurrentCulture <- System.Globalization.CultureInfo.InvariantCulture
            let props = 
              [ for (KeyValue(k, v)) in ch.CustomProperties -> 
                  sprintf "%s=%s" k (v.ToString()) ]
              |> String.concat ", "
            System.Threading.Thread.CurrentThread.CurrentCulture <- cult
            series.CustomProperties <- props

            ch.CustomPropertyChanged.Add(function
                (name, value) -> series.SetCustomProperty(name, System.String.Format(System.Globalization.CultureInfo.InvariantCulture, "{0}", value)))

            for leg in ch.Legends do
              let legend = new Legend()
              applyProperties legend leg
              legend.Name <- sprintf "Legend_%d" (legendCounter())
              legend.DockedToChartArea <- area.Name
              chart.Legends.Add legend
              series.Legend <- legend.Name
            createLegendChange chart ch [series]

            series

        match ch with
        | :? CombinedChart as cch ->
            let series = 
                [ for c in cch.Charts do
                    let s = processSeries c
                    processTitles c
                    yield s ]
            
            for leg in ch.Legends do
                let legend = new Legend()
                applyProperties legend leg
                legend.Name <- sprintf "Legend_%d" (legendCounter())
                legend.DockedToChartArea <- area.Name
                chart.Legends.Add legend
                for s in series do s.Legend <- legend.Name
            createLegendChange chart ch series

            processTitles cch
            series
        | c ->
            let series = processSeries c

            processTitles c
            [ series ]

    let createChart (ch:GenericChart) = 
        let chart = new Chart()
        applyPropertyDefaults (ch.ChartType) chart
        self.Controls.Add chart

        let rec loop (ch:GenericChart) (l, t, r, b) = 
            let (ml, mt, mr, mb) = ch.Margin
            let (l, t, r, b) = (l + ml, t + mt, r - mr, b - mb)
            match ch with
            | :? SubplotChart as subplot ->
                for title in ch.Titles do
                    chart.Titles.Add title
                createTitleChange chart ch
        
                let total = subplot.SplitSizes |> Seq.sum
                let available = if subplot.Orientation = Orientation.Vertical then b - t else r - l
                let k = float available / total

                let offs = ref 0.0f
                let series = 
                    [ for ch, siz in Seq.zip subplot.Charts subplot.SplitSizes do
                        if subplot.Orientation = Orientation.Vertical then
                          yield! loop ch (l, t + !offs, r, t + !offs + float32 (siz * k))
                        else
                          yield! loop ch (l + !offs, t, l + !offs + float32 (siz * k), b)
                        offs := !offs + float32 (siz * k) ]

                for leg in ch.Chart.Legends do
                    let legend = new Legend() 
                    applyProperties legend leg
                    legend.Name <- sprintf "Legend_%d" (legendCounter())
                    //legend.DockedToChartArea <- area.Name
                    chart.Legends.Add legend
                    for s in series do (s:Series).Legend <- legend.Name
                createLegendChange chart ch series

                series
            | _ ->
              createArea chart ch (l, t, r, b)

        let series = loop ch (0.0f, 0.0f, 100.0f, 100.0f)
        if ch.LazyChart.IsValueCreated then 
            applyProperties chart ch.Chart
        chart.Dock <- DockStyle.Fill
        ch.Chart <- chart

        chart, series
  
    let chart, series = createChart ch
    let props = new PropertyGrid(Width = 250, Dock = DockStyle.Right, SelectedObject = chart, Visible = false)
  
    do
      self.Controls.Add chart
      self.Controls.Add props

      let menu = new ContextMenu()
      let dlg = new SaveFileDialog(Filter = "PNG (*.png)|*.png|Bitmap (*.bmp;*.dib)|*.bmp;*.dib|GIF (*.gif)|*.gif|TIFF (*.tiff;*.tif)|*.tiff;*.tif|EMF (*.emf)|*.emf|JPEG (*.jpeg;*.jpg;*.jpe)|*.jpeg;*.jpg;*.jpe|EMF+ (*.emf)|*.emf|EMF+Dual (*.emf)|*.emf")
      let miCopy = new MenuItem("&Copy Image to Clipboard", Shortcut = Shortcut.CtrlC)
      let miCopyEmf = new MenuItem("Copy Image to Clipboard as &EMF", Shortcut = Shortcut.CtrlShiftC)
      let miSave = new MenuItem("&Save Image As..", Shortcut = Shortcut.CtrlS)
      let miEdit = new MenuItem("Show Property &Grid", Shortcut = Shortcut.CtrlG)

      miEdit.Click.Add(fun _ -> 
        miEdit.Checked <- not miEdit.Checked
        props.Visible <- miEdit.Checked)

      miCopy.Click.Add(fun _ ->        
        ch.CopyChartToClipboard())

      miCopyEmf.Click.Add(fun _ ->
        ch.CopyChartToClipboardEmf(self))

      miSave.Click.Add(fun _ ->
        if dlg.ShowDialog() = DialogResult.OK then
            let fmt = 
                match dlg.FilterIndex with
                | 1 -> ChartImageFormat.Png
                | 2 -> ChartImageFormat.Bmp
                | 3 -> ChartImageFormat.Gif
                | 4 -> ChartImageFormat.Tiff
                | 5 -> ChartImageFormat.Emf
                | 6 -> ChartImageFormat.Jpeg
                | 7 -> ChartImageFormat.EmfPlus
                | 8 -> ChartImageFormat.EmfDual
                | _ -> ChartImageFormat.Png
            chart.SaveImage(dlg.FileName, fmt) )

      menu.MenuItems.AddRange [| miCopy; miCopyEmf; miSave; miEdit |]
      self.ContextMenu <- menu

    member x.ChartSeries = seq { for s in series -> s }

// ----------------------------------- 
// Charting.FSharpChart.fs
// ----------------------------------- 
open ChartData.Internal
open ChartData
open ChartTypes
open ChartStyles

type FSharpChart =

    /// Displays multiple seriesÿof data as stacked areas. The cumulative proportion
    /// of each stacked element is always 100% of the Y axis.
    static member StackedArea100<'TY when 'TY :> IConvertible>(data: seq<'TY>) = 
        GenericChart<_>.Create<StackedArea100Chart>(oneY data)
    /// Displays multiple seriesÿof data as stacked areas. The cumulative proportion
    /// of each stacked element is always 100% of the Y axis.
    static member StackedArea100<'TX, 'TY when 'TX :> IConvertible and 'TY :> IConvertible>(data:seq<'TX * ('TY)>) = 
        GenericChart<_>.Create<StackedArea100Chart>(oneXYSeq data)
    /// Displays multiple seriesÿof data as stacked areas. The cumulative proportion
    /// of each stacked element is always 100% of the Y axis.
    static member StackedArea100<'TX, 'TY when 'TX :> IConvertible and 'TY :> IConvertible>(xvalues:seq<'TX>, yvalues: seq<'TY>) = 
        GenericChart<_>.Create<StackedArea100Chart>(oneXY xvalues yvalues)
    /// Displays multiple seriesÿof data as stacked areas. The cumulative proportion
    /// of each stacked element is always 100% of the Y axis.
    static member StackedArea100<'TY when 'TY :> IConvertible>(data:IObservable<'TY>, ?MaxPoints) = 
        GenericChart<_>.Create<StackedArea100Chart>(oneYObs (defaultArg MaxPoints -1) data)
    /// Displays multiple seriesÿof data as stacked areas. The cumulative proportion
    /// of each stacked element is always 100% of the Y axis.
    static member StackedArea100<'TX, 'TY when 'TY :> IConvertible and 'TX :> IConvertible>(data:IObservable<'TX * ('TY)>, ?MaxPoints) = 
        GenericChart<_>.Create<StackedArea100Chart>(oneXYObs (defaultArg MaxPoints -1) data)

    /// Displays multiple series of data as stacked bars. The cumulative
    /// proportion of each stacked element is always 100% of the Y axis.
    static member StackedBar100<'TY when 'TY :> IConvertible>(data: seq<'TY>) = 
        GenericChart<_>.Create<StackedBar100Chart>(oneY data)
    /// Displays multiple series of data as stacked bars. The cumulative
    /// proportion of each stacked element is always 100% of the Y axis.
    static member StackedBar100<'TX, 'TY when 'TX :> IConvertible and 'TY :> IConvertible>(data:seq<'TX * ('TY)>) = 
        GenericChart<_>.Create<StackedBar100Chart>(oneXYSeq data)
    /// Displays multiple series of data as stacked bars. The cumulative
    /// proportion of each stacked element is always 100% of the Y axis.
    static member StackedBar100<'TX, 'TY when 'TX :> IConvertible and 'TY :> IConvertible>(xvalues:seq<'TX>, yvalues: seq<'TY>) = 
        GenericChart<_>.Create<StackedBar100Chart>(oneXY xvalues yvalues)
    /// Displays multiple series of data as stacked bars. The cumulative
    /// proportion of each stacked element is always 100% of the Y axis.
    static member StackedBar100<'TY when 'TY :> IConvertible>(data:IObservable<'TY>, ?MaxPoints) = 
        GenericChart<_>.Create<StackedBar100Chart>(oneYObs (defaultArg MaxPoints -1) data)
    /// Displays multiple series of data as stacked bars. The cumulative
    /// proportion of each stacked element is always 100% of the Y axis.
    static member StackedBar100<'TX, 'TY when 'TY :> IConvertible and 'TX :> IConvertible>(data:IObservable<'TX * ('TY)>, ?MaxPoints) = 
        GenericChart<_>.Create<StackedBar100Chart>(oneXYObs (defaultArg MaxPoints -1) data)

    /// Displays multiple series of data as stacked columns. The cumulative
    /// proportion of each stacked element is always 100% of the Y axis.
    static member StackedColumn100<'TY when 'TY :> IConvertible>(data: seq<'TY>) = 
        GenericChart<_>.Create<StackedColumn100Chart>(oneY data)
    /// Displays multiple series of data as stacked columns. The cumulative
    /// proportion of each stacked element is always 100% of the Y axis.
    static member StackedColumn100<'TX, 'TY when 'TX :> IConvertible and 'TY :> IConvertible>(data:seq<'TX * ('TY)>) = 
        GenericChart<_>.Create<StackedColumn100Chart>(oneXYSeq data)
    /// Displays multiple series of data as stacked columns. The cumulative
    /// proportion of each stacked element is always 100% of the Y axis.
    static member StackedColumn100<'TX, 'TY when 'TX :> IConvertible and 'TY :> IConvertible>(xvalues:seq<'TX>, yvalues: seq<'TY>) = 
        GenericChart<_>.Create<StackedColumn100Chart>(oneXY xvalues yvalues)
    /// Displays multiple series of data as stacked columns. The cumulative
    /// proportion of each stacked element is always 100% of the Y axis.
    static member StackedColumn100<'TY when 'TY :> IConvertible>(data:IObservable<'TY>, ?MaxPoints) = 
        GenericChart<_>.Create<StackedColumn100Chart>(oneYObs (defaultArg MaxPoints -1) data)
    /// Displays multiple series of data as stacked columns. The cumulative
    /// proportion of each stacked element is always 100% of the Y axis.
    static member StackedColumn100<'TX, 'TY when 'TY :> IConvertible and 'TX :> IConvertible>(data:IObservable<'TX * ('TY)>, ?MaxPoints) = 
        GenericChart<_>.Create<StackedColumn100Chart>(oneXYObs (defaultArg MaxPoints -1) data)

    /// Emphasizes the degree of change over time and shows the
    /// relationship of the parts to a whole.
    static member Area<'TY when 'TY :> IConvertible>(data: seq<'TY>) = 
        GenericChart<_>.Create<AreaChart>(oneY data)
    /// Emphasizes the degree of change over time and shows the
    /// relationship of the parts to a whole.
    static member Area<'TX, 'TY when 'TX :> IConvertible and 'TY :> IConvertible>(data:seq<'TX * ('TY)>) = 
        GenericChart<_>.Create<AreaChart>(oneXYSeq data)
    /// Emphasizes the degree of change over time and shows the
    /// relationship of the parts to a whole.
    static member Area<'TX, 'TY when 'TX :> IConvertible and 'TY :> IConvertible>(xvalues:seq<'TX>, yvalues: seq<'TY>) = 
        GenericChart<_>.Create<AreaChart>(oneXY xvalues yvalues)
    /// Emphasizes the degree of change over time and shows the
    /// relationship of the parts to a whole.
    static member Area<'TY when 'TY :> IConvertible>(data:IObservable<'TY>, ?MaxPoints) = 
        GenericChart<_>.Create<AreaChart>(oneYObs (defaultArg MaxPoints -1) data)
    /// Emphasizes the degree of change over time and shows the
    /// relationship of the parts to a whole.
    static member Area<'TX, 'TY when 'TY :> IConvertible and 'TX :> IConvertible>(data:IObservable<'TX * ('TY)>, ?MaxPoints) = 
        GenericChart<_>.Create<AreaChart>(oneXYObs (defaultArg MaxPoints -1) data)

    /// Illustrates comparisons among individual items.
    static member Bar<'TY when 'TY :> IConvertible>(data: seq<'TY>) = 
        GenericChart<_>.Create<BarChart>(oneY data)
    /// Illustrates comparisons among individual items.
    static member Bar<'TX, 'TY when 'TX :> IConvertible and 'TY :> IConvertible>(data:seq<'TX * ('TY)>) = 
        GenericChart<_>.Create<BarChart>(oneXYSeq data)
    /// Illustrates comparisons among individual items.
    static member Bar<'TX, 'TY when 'TX :> IConvertible and 'TY :> IConvertible>(xvalues:seq<'TX>, yvalues: seq<'TY>) = 
        GenericChart<_>.Create<BarChart>(oneXY xvalues yvalues)
    /// Illustrates comparisons among individual items.
    static member Bar<'TY when 'TY :> IConvertible>(data:IObservable<'TY>, ?MaxPoints) = 
        GenericChart<_>.Create<BarChart>(oneYObs (defaultArg MaxPoints -1) data)
    /// Illustrates comparisons among individual items.
    static member Bar<'TX, 'TY when 'TY :> IConvertible and 'TX :> IConvertible>(data:IObservable<'TX * ('TY)>, ?MaxPoints) = 
        GenericChart<_>.Create<BarChart>(oneXYObs (defaultArg MaxPoints -1) data)

    /// Consists of one or more box symbols that summarize the
    /// distribution of the data withinÿone or moreÿdata sets.
    static member BoxPlot(data:seq<'T1 * 'T2 * 'T3 * 'T4 * 'T5 * 'T6>) = 
        GenericChart<_>.Create<BoxPlotChart>(sixY data)
    /// Consists of one or more box symbols that summarize the
    /// distribution of the data withinÿone or moreÿdata sets.
    static member BoxPlot(data:seq<'TX * 'TYValue[]>) = 
        GenericChart<_>.Create<BoxPlotChart>(sixXYArrBox data)
    /// Consists of one or more box symbols that summarize the
    /// distribution of the data withinÿone or moreÿdata sets.
    static member BoxPlot(data:seq<'TYValue[]>) =
        GenericChart<_>.Create<BoxPlotChart>(sixYArrBox data)

    /// A variation of the Point chart type, where the data
    /// points are replaced by bubbles of different sizes.
    static member Bubble<'TY1, 'TY2 when 'TY1 :> IConvertible and 'TY2 :> IConvertible>(data: seq<'TY1 * 'TY2>) = 
        GenericChart<_>.Create<BubbleChart>(twoY data)
    /// A variation of the Point chart type, where the data
    /// points are replaced by bubbles of different sizes.
    static member Bubble<'TX, 'TY1, 'TY2 when 'TX :> IConvertible and 'TY1 :> IConvertible and 'TY2 :> IConvertible>(data:seq<'TX * ('TY1 * 'TY2)>) = 
        GenericChart<_>.Create<BubbleChart>(twoXYSeq data)
    /// A variation of the Point chart type, where the data
    /// points are replaced by bubbles of different sizes.
    static member Bubble<'TX, 'TY1Values, 'TY1, 'TY2Values, 'TY2 when 'TX :> IConvertible and 'TY1 :> IConvertible and 'TY1Values :> seq<'TY1> and 'TY2 :> IConvertible and 'TY2Values :> seq<'TY2>>(xvalues:seq<'TX>, yvalues1:'TY1Values, yvalues2:'TY2Values) = 
        GenericChart<_>.Create<BubbleChart>(twoXY xvalues yvalues1 yvalues2)
    /// A variation of the Point chart type, where the data
    /// points are replaced by bubbles of different sizes.
    static member Bubble<'TY1, 'TY2 when 'TY1 :> IConvertible and 'TY2 :> IConvertible>(data:IObservable<'TY1 * 'TY2>, ?MaxPoints) = 
        GenericChart<_>.Create<BubbleChart>(twoYObs (defaultArg MaxPoints -1) data)
    /// A variation of the Point chart type, where the data
    /// points are replaced by bubbles of different sizes.
    static member Bubble<'TX, 'TY1, 'TY2 when 'TY1 :> IConvertible and 'TY2 :> IConvertible and 'TX :> IConvertible>(data:IObservable<'TX * ('TY1 * 'TY2)>, ?MaxPoints) = 
        GenericChart<_>.Create<BubbleChart>(twoXYObs (defaultArg MaxPoints -1) data)

    /// Used to display stock information using high, low, open and
    /// close values.
    static member Candlestick<'TY1, 'TY2, 'TY3, 'TY4 when 'TY1 :> IConvertible and 'TY2 :> IConvertible and 'TY3 :> IConvertible and 'TY4 :> IConvertible>(data: seq<'TY1 * 'TY2 * 'TY3 * 'TY4>) = 
        GenericChart<_>.Create<CandlestickChart>(fourY data)
    /// Used to display stock information using high, low, open and
    /// close values.
    static member Candlestick<'TX, 'TY1, 'TY2, 'TY3, 'TY4 when 'TX :> IConvertible and 'TY1 :> IConvertible and 'TY2 :> IConvertible and 'TY3 :> IConvertible and 'TY4 :> IConvertible>(data:seq<'TX * ('TY1 * 'TY2 * 'TY3 * 'TY4)>) = 
        GenericChart<_>.Create<CandlestickChart>(fourXYSeq data)
    /// Used to display stock information using high, low, open and
    /// close values.
    static member Candlestick<'TX, 'TY1Values, 'TY1, 'TY2Values, 'TY2, 'TY3Values, 'TY3, 'TY4Values, 'TY4 when 'TX :> IConvertible and 'TY1 :> IConvertible and 'TY1Values :> seq<'TY1> and 'TY2 :> IConvertible and 'TY2Values :> seq<'TY2> and 'TY3 :> IConvertible and 'TY3Values :> seq<'TY3> and 'TY4 :> IConvertible and 'TY4Values :> seq<'TY4>>(xvalues:seq<'TX>, yvalues1:'TY1Values, yvalues2:'TY2Values, yvalues3:'TY3Values, yvalues4:'TY4Values) = 
        GenericChart<_>.Create<CandlestickChart>(fourXY xvalues yvalues1 yvalues2 yvalues3 yvalues4)
    /// Used to display stock information using high, low, open and
    /// close values.
    static member Candlestick<'TY1, 'TY2, 'TY3, 'TY4 when 'TY1 :> IConvertible and 'TY2 :> IConvertible and 'TY3 :> IConvertible and 'TY4 :> IConvertible>(data:IObservable<'TY1 * 'TY2 * 'TY3 * 'TY4>, ?MaxPoints) = 
        GenericChart<_>.Create<CandlestickChart>(fourYObs (defaultArg MaxPoints -1) data)
    /// Used to display stock information using high, low, open and
    /// close values.
    static member Candlestick<'TX, 'TY1, 'TY2, 'TY3, 'TY4 when 'TY1 :> IConvertible and 'TY2 :> IConvertible and 'TY3 :> IConvertible and 'TY4 :> IConvertible and 'TX :> IConvertible>(data:IObservable<'TX * ('TY1 * 'TY2 * 'TY3 * 'TY4)>, ?MaxPoints) = 
        GenericChart<_>.Create<CandlestickChart>(fourXYObs (defaultArg MaxPoints -1) data)

    /// Uses a sequence of columns to compare values across categories.
    static member Column<'TY when 'TY :> IConvertible>(data: seq<'TY>) = 
        GenericChart<_>.Create<ColumnChart>(oneY data)
    /// Uses a sequence of columns to compare values across categories.
    static member Column<'TX, 'TY when 'TX :> IConvertible and 'TY :> IConvertible>(data:seq<'TX * ('TY)>) = 
        GenericChart<_>.Create<ColumnChart>(oneXYSeq data)
    /// Uses a sequence of columns to compare values across categories.
    static member Column<'TX, 'TY when 'TX :> IConvertible and 'TY :> IConvertible>(xvalues:seq<'TX>, yvalues: seq<'TY>) = 
        GenericChart<_>.Create<ColumnChart>(oneXY xvalues yvalues)
    /// Uses a sequence of columns to compare values across categories.
    static member Column<'TY when 'TY :> IConvertible>(data:IObservable<'TY>, ?MaxPoints) = 
        GenericChart<_>.Create<ColumnChart>(oneYObs (defaultArg MaxPoints -1) data)
    /// Uses a sequence of columns to compare values across categories.
    static member Column<'TX, 'TY when 'TY :> IConvertible and 'TX :> IConvertible>(data:IObservable<'TX * ('TY)>, ?MaxPoints) = 
        GenericChart<_>.Create<ColumnChart>(oneXYObs (defaultArg MaxPoints -1) data)

    /// Similar to the Pie chart type, except that it has
    /// a hole in the center.
    static member Doughnut<'TY when 'TY :> IConvertible>(data: seq<'TY>) = 
        GenericChart<_>.Create<DoughnutChart>(oneY data)
    /// Similar to the Pie chart type, except that it has
    /// a hole in the center.
    static member Doughnut<'TX, 'TY when 'TX :> IConvertible and 'TY :> IConvertible>(data:seq<'TX * ('TY)>) = 
        GenericChart<_>.Create<DoughnutChart>(oneXYSeq data)
    /// Similar to the Pie chart type, except that it has
    /// a hole in the center.
    static member Doughnut<'TX, 'TY when 'TX :> IConvertible and 'TY :> IConvertible>(xvalues:seq<'TX>, yvalues: seq<'TY>) = 
        GenericChart<_>.Create<DoughnutChart>(oneXY xvalues yvalues)
    /// Similar to the Pie chart type, except that it has
    /// a hole in the center.
    static member Doughnut<'TY when 'TY :> IConvertible>(data:IObservable<'TY>, ?MaxPoints) = 
        GenericChart<_>.Create<DoughnutChart>(oneYObs (defaultArg MaxPoints -1) data)
    /// Similar to the Pie chart type, except that it has
    /// a hole in the center.
    static member Doughnut<'TX, 'TY when 'TY :> IConvertible and 'TX :> IConvertible>(data:IObservable<'TX * ('TY)>, ?MaxPoints) = 
        GenericChart<_>.Create<DoughnutChart>(oneXYObs (defaultArg MaxPoints -1) data)

    /// Consists of lines with markers that are used to display
    /// statistical information about the data displayed inÿa graph.
    static member ErrorBar<'TY1, 'TY2, 'TY3 when 'TY1 :> IConvertible and 'TY2 :> IConvertible and 'TY3 :> IConvertible>(data: seq<'TY1 * 'TY2 * 'TY3>) = 
        GenericChart<_>.Create<ErrorBarChart>(threeY data)
    /// Consists of lines with markers that are used to display
    /// statistical information about the data displayed inÿa graph.
    static member ErrorBar<'TX, 'TY1, 'TY2, 'TY3 when 'TX :> IConvertible and 'TY1 :> IConvertible and 'TY2 :> IConvertible and 'TY3 :> IConvertible>(data:seq<'TX * ('TY1 * 'TY2 * 'TY3)>) = 
        GenericChart<_>.Create<ErrorBarChart>(threeXYSeq data)
    /// Consists of lines with markers that are used to display
    /// statistical information about the data displayed inÿa graph.
    static member ErrorBar<'TX, 'TY1Values, 'TY1, 'TY2Values, 'TY2, 'TY3Values, 'TY3 when 'TX :> IConvertible and 'TY1 :> IConvertible and 'TY1Values :> seq<'TY1> and 'TY2 :> IConvertible and 'TY2Values :> seq<'TY2> and 'TY3 :> IConvertible and 'TY3Values :> seq<'TY3>>(xvalues:seq<'TX>, yvalues1:'TY1Values, yvalues2:'TY2Values, yvalues3:'TY3Values) = 
        GenericChart<_>.Create<ErrorBarChart>(threeXY xvalues yvalues1 yvalues2 yvalues3)
    /// Consists of lines with markers that are used to display
    /// statistical information about the data displayed inÿa graph.
    static member ErrorBar<'TY1, 'TY2, 'TY3 when 'TY1 :> IConvertible and 'TY2 :> IConvertible and 'TY3 :> IConvertible>(data:IObservable<'TY1 * 'TY2 * 'TY3>, ?MaxPoints) = 
        GenericChart<_>.Create<ErrorBarChart>(threeYObs (defaultArg MaxPoints -1) data)
    /// Consists of lines with markers that are used to display
    /// statistical information about the data displayed inÿa graph.
    static member ErrorBar<'TX, 'TY1, 'TY2, 'TY3 when 'TY1 :> IConvertible and 'TY2 :> IConvertible and 'TY3 :> IConvertible and 'TX :> IConvertible>(data:IObservable<'TX * ('TY1 * 'TY2 * 'TY3)>, ?MaxPoints) = 
        GenericChart<_>.Create<ErrorBarChart>(threeXYObs (defaultArg MaxPoints -1) data)

    /// A variation of the Line chart that significantly reduces the
    /// drawing time of a series that contains a very large
    /// number of data points.
    static member FastLine<'TY when 'TY :> IConvertible>(data: seq<'TY>) = 
        GenericChart<_>.Create<FastLineChart>(oneY data)
    /// A variation of the Line chart that significantly reduces the
    /// drawing time of a series that contains a very large
    /// number of data points.
    static member FastLine<'TX, 'TY when 'TX :> IConvertible and 'TY :> IConvertible>(data:seq<'TX * ('TY)>) = 
        GenericChart<_>.Create<FastLineChart>(oneXYSeq data)
    /// A variation of the Line chart that significantly reduces the
    /// drawing time of a series that contains a very large
    /// number of data points.
    static member FastLine<'TX, 'TY when 'TX :> IConvertible and 'TY :> IConvertible>(xvalues:seq<'TX>, yvalues: seq<'TY>) = 
        GenericChart<_>.Create<FastLineChart>(oneXY xvalues yvalues)
    /// A variation of the Line chart that significantly reduces the
    /// drawing time of a series that contains a very large
    /// number of data points.
    static member FastLine<'TY when 'TY :> IConvertible>(data:IObservable<'TY>, ?MaxPoints) = 
        GenericChart<_>.Create<FastLineChart>(oneYObs (defaultArg MaxPoints -1) data)
    /// A variation of the Line chart that significantly reduces the
    /// drawing time of a series that contains a very large
    /// number of data points.
    static member FastLine<'TX, 'TY when 'TY :> IConvertible and 'TX :> IConvertible>(data:IObservable<'TX * ('TY)>, ?MaxPoints) = 
        GenericChart<_>.Create<FastLineChart>(oneXYObs (defaultArg MaxPoints -1) data)

    /// A variation of the Point chart type that significantly reduces
    /// the drawing time of a series that contains a very
    /// large number of data points.
    static member FastPoint<'TY when 'TY :> IConvertible>(data: seq<'TY>) = 
        GenericChart<_>.Create<FastPointChart>(oneY data)
    /// A variation of the Point chart type that significantly reduces
    /// the drawing time of a series that contains a very
    /// large number of data points.
    static member FastPoint<'TX, 'TY when 'TX :> IConvertible and 'TY :> IConvertible>(data:seq<'TX * ('TY)>) = 
        GenericChart<_>.Create<FastPointChart>(oneXYSeq data)
    /// A variation of the Point chart type that significantly reduces
    /// the drawing time of a series that contains a very
    /// large number of data points.
    static member FastPoint<'TX, 'TY when 'TX :> IConvertible and 'TY :> IConvertible>(xvalues:seq<'TX>, yvalues: seq<'TY>) = 
        GenericChart<_>.Create<FastPointChart>(oneXY xvalues yvalues)
    /// A variation of the Point chart type that significantly reduces
    /// the drawing time of a series that contains a very
    /// large number of data points.
    static member FastPoint<'TY when 'TY :> IConvertible>(data:IObservable<'TY>, ?MaxPoints) = 
        GenericChart<_>.Create<FastPointChart>(oneYObs (defaultArg MaxPoints -1) data)
    /// A variation of the Point chart type that significantly reduces
    /// the drawing time of a series that contains a very
    /// large number of data points.
    static member FastPoint<'TX, 'TY when 'TY :> IConvertible and 'TX :> IConvertible>(data:IObservable<'TX * ('TY)>, ?MaxPoints) = 
        GenericChart<_>.Create<FastPointChart>(oneXYObs (defaultArg MaxPoints -1) data)

    /// Displays in a funnel shape data that equals 100% when
    /// totaled.
    static member Funnel<'TY when 'TY :> IConvertible>(data: seq<'TY>) = 
        GenericChart<_>.Create<FunnelChart>(oneY data)
    /// Displays in a funnel shape data that equals 100% when
    /// totaled.
    static member Funnel<'TX, 'TY when 'TX :> IConvertible and 'TY :> IConvertible>(data:seq<'TX * ('TY)>) = 
        GenericChart<_>.Create<FunnelChart>(oneXYSeq data)
    /// Displays in a funnel shape data that equals 100% when
    /// totaled.
    static member Funnel<'TX, 'TY when 'TX :> IConvertible and 'TY :> IConvertible>(xvalues:seq<'TX>, yvalues: seq<'TY>) = 
        GenericChart<_>.Create<FunnelChart>(oneXY xvalues yvalues)
    /// Displays in a funnel shape data that equals 100% when
    /// totaled.
    static member Funnel<'TY when 'TY :> IConvertible>(data:IObservable<'TY>, ?MaxPoints) = 
        GenericChart<_>.Create<FunnelChart>(oneYObs (defaultArg MaxPoints -1) data)
    /// Displays in a funnel shape data that equals 100% when
    /// totaled.
    static member Funnel<'TX, 'TY when 'TY :> IConvertible and 'TX :> IConvertible>(data:IObservable<'TX * ('TY)>, ?MaxPoints) = 
        GenericChart<_>.Create<FunnelChart>(oneXYObs (defaultArg MaxPoints -1) data)

    /// Displays a series of connecting vertical lines where the thickness
    /// and direction of the lines are dependent on the action
    /// of the price value.
    static member Kagi<'TY when 'TY :> IConvertible>(data: seq<'TY>) = 
        GenericChart<_>.Create<KagiChart>(oneY data)
    /// Displays a series of connecting vertical lines where the thickness
    /// and direction of the lines are dependent on the action
    /// of the price value.
    static member Kagi<'TX, 'TY when 'TX :> IConvertible and 'TY :> IConvertible>(data:seq<'TX * ('TY)>) = 
        GenericChart<_>.Create<KagiChart>(oneXYSeq data)
    /// Displays a series of connecting vertical lines where the thickness
    /// and direction of the lines are dependent on the action
    /// of the price value.
    static member Kagi<'TX, 'TY when 'TX :> IConvertible and 'TY :> IConvertible>(xvalues:seq<'TX>, yvalues: seq<'TY>) = 
        GenericChart<_>.Create<KagiChart>(oneXY xvalues yvalues)
    /// Displays a series of connecting vertical lines where the thickness
    /// and direction of the lines are dependent on the action
    /// of the price value.
    static member Kagi<'TY when 'TY :> IConvertible>(data:IObservable<'TY>, ?MaxPoints) = 
        GenericChart<_>.Create<KagiChart>(oneYObs (defaultArg MaxPoints -1) data)
    /// Displays a series of connecting vertical lines where the thickness
    /// and direction of the lines are dependent on the action
    /// of the price value.
    static member Kagi<'TX, 'TY when 'TY :> IConvertible and 'TX :> IConvertible>(data:IObservable<'TX * ('TY)>, ?MaxPoints) = 
        GenericChart<_>.Create<KagiChart>(oneXYObs (defaultArg MaxPoints -1) data)

    /// Illustrates trends in data with the passing of time.
    static member Line<'TY when 'TY :> IConvertible>(data: seq<'TY>) = 
        GenericChart<_>.Create<LineChart>(oneY data)
    /// Illustrates trends in data with the passing of time.
    static member Line<'TX, 'TY when 'TX :> IConvertible and 'TY :> IConvertible>(data:seq<'TX * ('TY)>) = 
        GenericChart<_>.Create<LineChart>(oneXYSeq data)
    /// Illustrates trends in data with the passing of time.
    static member Line<'TX, 'TY when 'TX :> IConvertible and 'TY :> IConvertible>(xvalues:seq<'TX>, yvalues: seq<'TY>) = 
        GenericChart<_>.Create<LineChart>(oneXY xvalues yvalues)
    /// Illustrates trends in data with the passing of time.
    static member Line<'TY when 'TY :> IConvertible>(data:IObservable<'TY>, ?MaxPoints) = 
        GenericChart<_>.Create<LineChart>(oneYObs (defaultArg MaxPoints -1) data)
    /// Illustrates trends in data with the passing of time.
    static member Line<'TX, 'TY when 'TY :> IConvertible and 'TX :> IConvertible>(data:IObservable<'TX * ('TY)>, ?MaxPoints) = 
        GenericChart<_>.Create<LineChart>(oneXYObs (defaultArg MaxPoints -1) data)

    /// Shows how proportions of data, shown as pie-shaped pieces,ÿcontribute to
    /// the data as aÿwhole.
    static member Pie<'TY when 'TY :> IConvertible>(data: seq<'TY>) = 
        GenericChart<_>.Create<PieChart>(oneY data)
    /// Shows how proportions of data, shown as pie-shaped pieces,ÿcontribute to
    /// the data as aÿwhole.
    static member Pie<'TX, 'TY when 'TX :> IConvertible and 'TY :> IConvertible>(data:seq<'TX * ('TY)>) = 
        GenericChart<_>.Create<PieChart>(oneXYSeq data)
    /// Shows how proportions of data, shown as pie-shaped pieces,ÿcontribute to
    /// the data as aÿwhole.
    static member Pie<'TX, 'TY when 'TX :> IConvertible and 'TY :> IConvertible>(xvalues:seq<'TX>, yvalues: seq<'TY>) = 
        GenericChart<_>.Create<PieChart>(oneXY xvalues yvalues)
    /// Shows how proportions of data, shown as pie-shaped pieces,ÿcontribute to
    /// the data as aÿwhole.
    static member Pie<'TY when 'TY :> IConvertible>(data:IObservable<'TY>, ?MaxPoints) = 
        GenericChart<_>.Create<PieChart>(oneYObs (defaultArg MaxPoints -1) data)
    /// Shows how proportions of data, shown as pie-shaped pieces,ÿcontribute to
    /// the data as aÿwhole.
    static member Pie<'TX, 'TY when 'TY :> IConvertible and 'TX :> IConvertible>(data:IObservable<'TX * ('TY)>, ?MaxPoints) = 
        GenericChart<_>.Create<PieChart>(oneXYObs (defaultArg MaxPoints -1) data)

    /// Uses points to represent data points.
    static member Point<'TY when 'TY :> IConvertible>(data: seq<'TY>) = 
        GenericChart<_>.Create<PointChart>(oneY data)
    /// Uses points to represent data points.
    static member Point<'TX, 'TY when 'TX :> IConvertible and 'TY :> IConvertible>(data:seq<'TX * ('TY)>) = 
        GenericChart<_>.Create<PointChart>(oneXYSeq data)
    /// Uses points to represent data points.
    static member Point<'TX, 'TY when 'TX :> IConvertible and 'TY :> IConvertible>(xvalues:seq<'TX>, yvalues: seq<'TY>) = 
        GenericChart<_>.Create<PointChart>(oneXY xvalues yvalues)
    /// Uses points to represent data points.
    static member Point<'TY when 'TY :> IConvertible>(data:IObservable<'TY>, ?MaxPoints) = 
        GenericChart<_>.Create<PointChart>(oneYObs (defaultArg MaxPoints -1) data)
    /// Uses points to represent data points.
    static member Point<'TX, 'TY when 'TY :> IConvertible and 'TX :> IConvertible>(data:IObservable<'TX * ('TY)>, ?MaxPoints) = 
        GenericChart<_>.Create<PointChart>(oneXYObs (defaultArg MaxPoints -1) data)

    /// Disregards the passage of time and only displays changes in
    /// prices.
    static member PointAndFigure<'TY1, 'TY2 when 'TY1 :> IConvertible and 'TY2 :> IConvertible>(data: seq<'TY1 * 'TY2>) = 
        GenericChart<_>.Create<PointAndFigureChart>(twoY data)
    /// Disregards the passage of time and only displays changes in
    /// prices.
    static member PointAndFigure<'TX, 'TY1, 'TY2 when 'TX :> IConvertible and 'TY1 :> IConvertible and 'TY2 :> IConvertible>(data:seq<'TX * ('TY1 * 'TY2)>) = 
        GenericChart<_>.Create<PointAndFigureChart>(twoXYSeq data)
    /// Disregards the passage of time and only displays changes in
    /// prices.
    static member PointAndFigure<'TX, 'TY1Values, 'TY1, 'TY2Values, 'TY2 when 'TX :> IConvertible and 'TY1 :> IConvertible and 'TY1Values :> seq<'TY1> and 'TY2 :> IConvertible and 'TY2Values :> seq<'TY2>>(xvalues:seq<'TX>, yvalues1:'TY1Values, yvalues2:'TY2Values) = 
        GenericChart<_>.Create<PointAndFigureChart>(twoXY xvalues yvalues1 yvalues2)
    /// Disregards the passage of time and only displays changes in
    /// prices.
    static member PointAndFigure<'TY1, 'TY2 when 'TY1 :> IConvertible and 'TY2 :> IConvertible>(data:IObservable<'TY1 * 'TY2>, ?MaxPoints) = 
        GenericChart<_>.Create<PointAndFigureChart>(twoYObs (defaultArg MaxPoints -1) data)
    /// Disregards the passage of time and only displays changes in
    /// prices.
    static member PointAndFigure<'TX, 'TY1, 'TY2 when 'TY1 :> IConvertible and 'TY2 :> IConvertible and 'TX :> IConvertible>(data:IObservable<'TX * ('TY1 * 'TY2)>, ?MaxPoints) = 
        GenericChart<_>.Create<PointAndFigureChart>(twoXYObs (defaultArg MaxPoints -1) data)

    /// A circular graph on which data points are displayed using
    /// the angle, and the distance from the center point.
    static member Polar<'TY when 'TY :> IConvertible>(data: seq<'TY>) = 
        GenericChart<_>.Create<PolarChart>(oneY data)
    /// A circular graph on which data points are displayed using
    /// the angle, and the distance from the center point.
    static member Polar<'TX, 'TY when 'TX :> IConvertible and 'TY :> IConvertible>(data:seq<'TX * ('TY)>) = 
        GenericChart<_>.Create<PolarChart>(oneXYSeq data)
    /// A circular graph on which data points are displayed using
    /// the angle, and the distance from the center point.
    static member Polar<'TX, 'TY when 'TX :> IConvertible and 'TY :> IConvertible>(xvalues:seq<'TX>, yvalues: seq<'TY>) = 
        GenericChart<_>.Create<PolarChart>(oneXY xvalues yvalues)
    /// A circular graph on which data points are displayed using
    /// the angle, and the distance from the center point.
    static member Polar<'TY when 'TY :> IConvertible>(data:IObservable<'TY>, ?MaxPoints) = 
        GenericChart<_>.Create<PolarChart>(oneYObs (defaultArg MaxPoints -1) data)
    /// A circular graph on which data points are displayed using
    /// the angle, and the distance from the center point.
    static member Polar<'TX, 'TY when 'TY :> IConvertible and 'TX :> IConvertible>(data:IObservable<'TX * ('TY)>, ?MaxPoints) = 
        GenericChart<_>.Create<PolarChart>(oneXYObs (defaultArg MaxPoints -1) data)

    /// Displays data that, when combined, equals 100%.
    static member Pyramid<'TY when 'TY :> IConvertible>(data: seq<'TY>) = 
        GenericChart<_>.Create<PyramidChart>(oneY data)
    /// Displays data that, when combined, equals 100%.
    static member Pyramid<'TX, 'TY when 'TX :> IConvertible and 'TY :> IConvertible>(data:seq<'TX * ('TY)>) = 
        GenericChart<_>.Create<PyramidChart>(oneXYSeq data)
    /// Displays data that, when combined, equals 100%.
    static member Pyramid<'TX, 'TY when 'TX :> IConvertible and 'TY :> IConvertible>(xvalues:seq<'TX>, yvalues: seq<'TY>) = 
        GenericChart<_>.Create<PyramidChart>(oneXY xvalues yvalues)
    /// Displays data that, when combined, equals 100%.
    static member Pyramid<'TY when 'TY :> IConvertible>(data:IObservable<'TY>, ?MaxPoints) = 
        GenericChart<_>.Create<PyramidChart>(oneYObs (defaultArg MaxPoints -1) data)
    /// Displays data that, when combined, equals 100%.
    static member Pyramid<'TX, 'TY when 'TY :> IConvertible and 'TX :> IConvertible>(data:IObservable<'TX * ('TY)>, ?MaxPoints) = 
        GenericChart<_>.Create<PyramidChart>(oneXYObs (defaultArg MaxPoints -1) data)

    /// A circular chart that is used primarily as a data
    /// comparison tool.
    static member Radar<'TY when 'TY :> IConvertible>(data: seq<'TY>) = 
        GenericChart<_>.Create<RadarChart>(oneY data)
    /// A circular chart that is used primarily as a data
    /// comparison tool.
    static member Radar<'TX, 'TY when 'TX :> IConvertible and 'TY :> IConvertible>(data:seq<'TX * ('TY)>) = 
        GenericChart<_>.Create<RadarChart>(oneXYSeq data)
    /// A circular chart that is used primarily as a data
    /// comparison tool.
    static member Radar<'TX, 'TY when 'TX :> IConvertible and 'TY :> IConvertible>(xvalues:seq<'TX>, yvalues: seq<'TY>) = 
        GenericChart<_>.Create<RadarChart>(oneXY xvalues yvalues)
    /// A circular chart that is used primarily as a data
    /// comparison tool.
    static member Radar<'TY when 'TY :> IConvertible>(data:IObservable<'TY>, ?MaxPoints) = 
        GenericChart<_>.Create<RadarChart>(oneYObs (defaultArg MaxPoints -1) data)
    /// A circular chart that is used primarily as a data
    /// comparison tool.
    static member Radar<'TX, 'TY when 'TY :> IConvertible and 'TX :> IConvertible>(data:IObservable<'TX * ('TY)>, ?MaxPoints) = 
        GenericChart<_>.Create<RadarChart>(oneXYObs (defaultArg MaxPoints -1) data)

    /// Displays a range of data by plottingÿtwoÿY values per data
    /// point, with each Y value being drawn as a line
    /// chart.
    static member Range<'TY1, 'TY2 when 'TY1 :> IConvertible and 'TY2 :> IConvertible>(data: seq<'TY1 * 'TY2>) = 
        GenericChart<_>.Create<RangeChart>(twoY data)
    /// Displays a range of data by plottingÿtwoÿY values per data
    /// point, with each Y value being drawn as a line
    /// chart.
    static member Range<'TX, 'TY1, 'TY2 when 'TX :> IConvertible and 'TY1 :> IConvertible and 'TY2 :> IConvertible>(data:seq<'TX * ('TY1 * 'TY2)>) = 
        GenericChart<_>.Create<RangeChart>(twoXYSeq data)
    /// Displays a range of data by plottingÿtwoÿY values per data
    /// point, with each Y value being drawn as a line
    /// chart.
    static member Range<'TX, 'TY1Values, 'TY1, 'TY2Values, 'TY2 when 'TX :> IConvertible and 'TY1 :> IConvertible and 'TY1Values :> seq<'TY1> and 'TY2 :> IConvertible and 'TY2Values :> seq<'TY2>>(xvalues:seq<'TX>, yvalues1:'TY1Values, yvalues2:'TY2Values) = 
        GenericChart<_>.Create<RangeChart>(twoXY xvalues yvalues1 yvalues2)
    /// Displays a range of data by plottingÿtwoÿY values per data
    /// point, with each Y value being drawn as a line
    /// chart.
    static member Range<'TY1, 'TY2 when 'TY1 :> IConvertible and 'TY2 :> IConvertible>(data:IObservable<'TY1 * 'TY2>, ?MaxPoints) = 
        GenericChart<_>.Create<RangeChart>(twoYObs (defaultArg MaxPoints -1) data)
    /// Displays a range of data by plottingÿtwoÿY values per data
    /// point, with each Y value being drawn as a line
    /// chart.
    static member Range<'TX, 'TY1, 'TY2 when 'TY1 :> IConvertible and 'TY2 :> IConvertible and 'TX :> IConvertible>(data:IObservable<'TX * ('TY1 * 'TY2)>, ?MaxPoints) = 
        GenericChart<_>.Create<RangeChart>(twoXYObs (defaultArg MaxPoints -1) data)

    /// Displays separate events that have beginning and end values.
    static member RangeBar<'TY1, 'TY2 when 'TY1 :> IConvertible and 'TY2 :> IConvertible>(data: seq<'TY1 * 'TY2>) = 
        GenericChart<_>.Create<RangeBarChart>(twoY data)
    /// Displays separate events that have beginning and end values.
    static member RangeBar<'TX, 'TY1, 'TY2 when 'TX :> IConvertible and 'TY1 :> IConvertible and 'TY2 :> IConvertible>(data:seq<'TX * ('TY1 * 'TY2)>) = 
        GenericChart<_>.Create<RangeBarChart>(twoXYSeq data)
    /// Displays separate events that have beginning and end values.
    static member RangeBar<'TX, 'TY1Values, 'TY1, 'TY2Values, 'TY2 when 'TX :> IConvertible and 'TY1 :> IConvertible and 'TY1Values :> seq<'TY1> and 'TY2 :> IConvertible and 'TY2Values :> seq<'TY2>>(xvalues:seq<'TX>, yvalues1:'TY1Values, yvalues2:'TY2Values) = 
        GenericChart<_>.Create<RangeBarChart>(twoXY xvalues yvalues1 yvalues2)
    /// Displays separate events that have beginning and end values.
    static member RangeBar<'TY1, 'TY2 when 'TY1 :> IConvertible and 'TY2 :> IConvertible>(data:IObservable<'TY1 * 'TY2>, ?MaxPoints) = 
        GenericChart<_>.Create<RangeBarChart>(twoYObs (defaultArg MaxPoints -1) data)
    /// Displays separate events that have beginning and end values.
    static member RangeBar<'TX, 'TY1, 'TY2 when 'TY1 :> IConvertible and 'TY2 :> IConvertible and 'TX :> IConvertible>(data:IObservable<'TX * ('TY1 * 'TY2)>, ?MaxPoints) = 
        GenericChart<_>.Create<RangeBarChart>(twoXYObs (defaultArg MaxPoints -1) data)

    /// Displays a range of data by plotting two Y values
    /// per data point.
    static member RangeColumn<'TY1, 'TY2 when 'TY1 :> IConvertible and 'TY2 :> IConvertible>(data: seq<'TY1 * 'TY2>) = 
        GenericChart<_>.Create<RangeColumnChart>(twoY data)
    /// Displays a range of data by plotting two Y values
    /// per data point.
    static member RangeColumn<'TX, 'TY1, 'TY2 when 'TX :> IConvertible and 'TY1 :> IConvertible and 'TY2 :> IConvertible>(data:seq<'TX * ('TY1 * 'TY2)>) = 
        GenericChart<_>.Create<RangeColumnChart>(twoXYSeq data)
    /// Displays a range of data by plotting two Y values
    /// per data point.
    static member RangeColumn<'TX, 'TY1Values, 'TY1, 'TY2Values, 'TY2 when 'TX :> IConvertible and 'TY1 :> IConvertible and 'TY1Values :> seq<'TY1> and 'TY2 :> IConvertible and 'TY2Values :> seq<'TY2>>(xvalues:seq<'TX>, yvalues1:'TY1Values, yvalues2:'TY2Values) = 
        GenericChart<_>.Create<RangeColumnChart>(twoXY xvalues yvalues1 yvalues2)
    /// Displays a range of data by plotting two Y values
    /// per data point.
    static member RangeColumn<'TY1, 'TY2 when 'TY1 :> IConvertible and 'TY2 :> IConvertible>(data:IObservable<'TY1 * 'TY2>, ?MaxPoints) = 
        GenericChart<_>.Create<RangeColumnChart>(twoYObs (defaultArg MaxPoints -1) data)
    /// Displays a range of data by plotting two Y values
    /// per data point.
    static member RangeColumn<'TX, 'TY1, 'TY2 when 'TY1 :> IConvertible and 'TY2 :> IConvertible and 'TX :> IConvertible>(data:IObservable<'TX * ('TY1 * 'TY2)>, ?MaxPoints) = 
        GenericChart<_>.Create<RangeColumnChart>(twoXYObs (defaultArg MaxPoints -1) data)

    /// Displays a series of connecting vertical lines where the thickness
    /// and direction of the lines are dependent on the action
    /// of the price value.
    static member Renko<'TY when 'TY :> IConvertible>(data: seq<'TY>) = 
        GenericChart<_>.Create<RenkoChart>(oneY data)
    /// Displays a series of connecting vertical lines where the thickness
    /// and direction of the lines are dependent on the action
    /// of the price value.
    static member Renko<'TX, 'TY when 'TX :> IConvertible and 'TY :> IConvertible>(data:seq<'TX * ('TY)>) = 
        GenericChart<_>.Create<RenkoChart>(oneXYSeq data)
    /// Displays a series of connecting vertical lines where the thickness
    /// and direction of the lines are dependent on the action
    /// of the price value.
    static member Renko<'TX, 'TY when 'TX :> IConvertible and 'TY :> IConvertible>(xvalues:seq<'TX>, yvalues: seq<'TY>) = 
        GenericChart<_>.Create<RenkoChart>(oneXY xvalues yvalues)
    /// Displays a series of connecting vertical lines where the thickness
    /// and direction of the lines are dependent on the action
    /// of the price value.
    static member Renko<'TY when 'TY :> IConvertible>(data:IObservable<'TY>, ?MaxPoints) = 
        GenericChart<_>.Create<RenkoChart>(oneYObs (defaultArg MaxPoints -1) data)
    /// Displays a series of connecting vertical lines where the thickness
    /// and direction of the lines are dependent on the action
    /// of the price value.
    static member Renko<'TX, 'TY when 'TY :> IConvertible and 'TX :> IConvertible>(data:IObservable<'TX * ('TY)>, ?MaxPoints) = 
        GenericChart<_>.Create<RenkoChart>(oneXYObs (defaultArg MaxPoints -1) data)

    /// A Line chart that plots a fitted curve through each
    /// data point in a series.
    static member Spline<'TY when 'TY :> IConvertible>(data: seq<'TY>) = 
        GenericChart<_>.Create<SplineChart>(oneY data)
    /// A Line chart that plots a fitted curve through each
    /// data point in a series.
    static member Spline<'TX, 'TY when 'TX :> IConvertible and 'TY :> IConvertible>(data:seq<'TX * ('TY)>) = 
        GenericChart<_>.Create<SplineChart>(oneXYSeq data)
    /// A Line chart that plots a fitted curve through each
    /// data point in a series.
    static member Spline<'TX, 'TY when 'TX :> IConvertible and 'TY :> IConvertible>(xvalues:seq<'TX>, yvalues: seq<'TY>) = 
        GenericChart<_>.Create<SplineChart>(oneXY xvalues yvalues)
    /// A Line chart that plots a fitted curve through each
    /// data point in a series.
    static member Spline<'TY when 'TY :> IConvertible>(data:IObservable<'TY>, ?MaxPoints) = 
        GenericChart<_>.Create<SplineChart>(oneYObs (defaultArg MaxPoints -1) data)
    /// A Line chart that plots a fitted curve through each
    /// data point in a series.
    static member Spline<'TX, 'TY when 'TY :> IConvertible and 'TX :> IConvertible>(data:IObservable<'TX * ('TY)>, ?MaxPoints) = 
        GenericChart<_>.Create<SplineChart>(oneXYObs (defaultArg MaxPoints -1) data)

    /// An Area chart that plots a fitted curve through each
    /// data point in a series.
    static member SplineArea<'TY when 'TY :> IConvertible>(data: seq<'TY>) = 
        GenericChart<_>.Create<SplineAreaChart>(oneY data)
    /// An Area chart that plots a fitted curve through each
    /// data point in a series.
    static member SplineArea<'TX, 'TY when 'TX :> IConvertible and 'TY :> IConvertible>(data:seq<'TX * ('TY)>) = 
        GenericChart<_>.Create<SplineAreaChart>(oneXYSeq data)
    /// An Area chart that plots a fitted curve through each
    /// data point in a series.
    static member SplineArea<'TX, 'TY when 'TX :> IConvertible and 'TY :> IConvertible>(xvalues:seq<'TX>, yvalues: seq<'TY>) = 
        GenericChart<_>.Create<SplineAreaChart>(oneXY xvalues yvalues)
    /// An Area chart that plots a fitted curve through each
    /// data point in a series.
    static member SplineArea<'TY when 'TY :> IConvertible>(data:IObservable<'TY>, ?MaxPoints) = 
        GenericChart<_>.Create<SplineAreaChart>(oneYObs (defaultArg MaxPoints -1) data)
    /// An Area chart that plots a fitted curve through each
    /// data point in a series.
    static member SplineArea<'TX, 'TY when 'TY :> IConvertible and 'TX :> IConvertible>(data:IObservable<'TX * ('TY)>, ?MaxPoints) = 
        GenericChart<_>.Create<SplineAreaChart>(oneXYObs (defaultArg MaxPoints -1) data)

    /// Displays a range of data by plotting twoÿY values per
    /// data point, with each Y value drawn as a line
    /// chart.
    static member SplineRange<'TY1, 'TY2 when 'TY1 :> IConvertible and 'TY2 :> IConvertible>(data: seq<'TY1 * 'TY2>) = 
        GenericChart<_>.Create<SplineRangeChart>(twoY data)
    /// Displays a range of data by plotting twoÿY values per
    /// data point, with each Y value drawn as a line
    /// chart.
    static member SplineRange<'TX, 'TY1, 'TY2 when 'TX :> IConvertible and 'TY1 :> IConvertible and 'TY2 :> IConvertible>(data:seq<'TX * ('TY1 * 'TY2)>) = 
        GenericChart<_>.Create<SplineRangeChart>(twoXYSeq data)
    /// Displays a range of data by plotting twoÿY values per
    /// data point, with each Y value drawn as a line
    /// chart.
    static member SplineRange<'TX, 'TY1Values, 'TY1, 'TY2Values, 'TY2 when 'TX :> IConvertible and 'TY1 :> IConvertible and 'TY1Values :> seq<'TY1> and 'TY2 :> IConvertible and 'TY2Values :> seq<'TY2>>(xvalues:seq<'TX>, yvalues1:'TY1Values, yvalues2:'TY2Values) = 
        GenericChart<_>.Create<SplineRangeChart>(twoXY xvalues yvalues1 yvalues2)
    /// Displays a range of data by plotting twoÿY values per
    /// data point, with each Y value drawn as a line
    /// chart.
    static member SplineRange<'TY1, 'TY2 when 'TY1 :> IConvertible and 'TY2 :> IConvertible>(data:IObservable<'TY1 * 'TY2>, ?MaxPoints) = 
        GenericChart<_>.Create<SplineRangeChart>(twoYObs (defaultArg MaxPoints -1) data)
    /// Displays a range of data by plotting twoÿY values per
    /// data point, with each Y value drawn as a line
    /// chart.
    static member SplineRange<'TX, 'TY1, 'TY2 when 'TY1 :> IConvertible and 'TY2 :> IConvertible and 'TX :> IConvertible>(data:IObservable<'TX * ('TY1 * 'TY2)>, ?MaxPoints) = 
        GenericChart<_>.Create<SplineRangeChart>(twoXYObs (defaultArg MaxPoints -1) data)

    /// An Area chart that stacks two or more data series
    /// on top of one another.
    static member StackedArea<'TY when 'TY :> IConvertible>(data: seq<'TY>) = 
        GenericChart<_>.Create<StackedAreaChart>(oneY data)
    /// An Area chart that stacks two or more data series
    /// on top of one another.
    static member StackedArea<'TX, 'TY when 'TX :> IConvertible and 'TY :> IConvertible>(data:seq<'TX * ('TY)>) = 
        GenericChart<_>.Create<StackedAreaChart>(oneXYSeq data)
    /// An Area chart that stacks two or more data series
    /// on top of one another.
    static member StackedArea<'TX, 'TY when 'TX :> IConvertible and 'TY :> IConvertible>(xvalues:seq<'TX>, yvalues: seq<'TY>) = 
        GenericChart<_>.Create<StackedAreaChart>(oneXY xvalues yvalues)
    /// An Area chart that stacks two or more data series
    /// on top of one another.
    static member StackedArea<'TY when 'TY :> IConvertible>(data:IObservable<'TY>, ?MaxPoints) = 
        GenericChart<_>.Create<StackedAreaChart>(oneYObs (defaultArg MaxPoints -1) data)
    /// An Area chart that stacks two or more data series
    /// on top of one another.
    static member StackedArea<'TX, 'TY when 'TY :> IConvertible and 'TX :> IConvertible>(data:IObservable<'TX * ('TY)>, ?MaxPoints) = 
        GenericChart<_>.Create<StackedAreaChart>(oneXYObs (defaultArg MaxPoints -1) data)

    /// Displays series of the same chart type as stacked bars.
    static member StackedBar<'TY when 'TY :> IConvertible>(data: seq<'TY>) = 
        GenericChart<_>.Create<StackedBarChart>(oneY data)
    /// Displays series of the same chart type as stacked bars.
    static member StackedBar<'TX, 'TY when 'TX :> IConvertible and 'TY :> IConvertible>(data:seq<'TX * ('TY)>) = 
        GenericChart<_>.Create<StackedBarChart>(oneXYSeq data)
    /// Displays series of the same chart type as stacked bars.
    static member StackedBar<'TX, 'TY when 'TX :> IConvertible and 'TY :> IConvertible>(xvalues:seq<'TX>, yvalues: seq<'TY>) = 
        GenericChart<_>.Create<StackedBarChart>(oneXY xvalues yvalues)
    /// Displays series of the same chart type as stacked bars.
    static member StackedBar<'TY when 'TY :> IConvertible>(data:IObservable<'TY>, ?MaxPoints) = 
        GenericChart<_>.Create<StackedBarChart>(oneYObs (defaultArg MaxPoints -1) data)
    /// Displays series of the same chart type as stacked bars.
    static member StackedBar<'TX, 'TY when 'TY :> IConvertible and 'TX :> IConvertible>(data:IObservable<'TX * ('TY)>, ?MaxPoints) = 
        GenericChart<_>.Create<StackedBarChart>(oneXYObs (defaultArg MaxPoints -1) data)

    /// Used to compare the contribution of each value to a
    /// total across categories.
    static member StackedColumn<'TY when 'TY :> IConvertible>(data: seq<'TY>) = 
        GenericChart<_>.Create<StackedColumnChart>(oneY data)
    /// Used to compare the contribution of each value to a
    /// total across categories.
    static member StackedColumn<'TX, 'TY when 'TX :> IConvertible and 'TY :> IConvertible>(data:seq<'TX * ('TY)>) = 
        GenericChart<_>.Create<StackedColumnChart>(oneXYSeq data)
    /// Used to compare the contribution of each value to a
    /// total across categories.
    static member StackedColumn<'TX, 'TY when 'TX :> IConvertible and 'TY :> IConvertible>(xvalues:seq<'TX>, yvalues: seq<'TY>) = 
        GenericChart<_>.Create<StackedColumnChart>(oneXY xvalues yvalues)
    /// Used to compare the contribution of each value to a
    /// total across categories.
    static member StackedColumn<'TY when 'TY :> IConvertible>(data:IObservable<'TY>, ?MaxPoints) = 
        GenericChart<_>.Create<StackedColumnChart>(oneYObs (defaultArg MaxPoints -1) data)
    /// Used to compare the contribution of each value to a
    /// total across categories.
    static member StackedColumn<'TX, 'TY when 'TY :> IConvertible and 'TX :> IConvertible>(data:IObservable<'TX * ('TY)>, ?MaxPoints) = 
        GenericChart<_>.Create<StackedColumnChart>(oneXYObs (defaultArg MaxPoints -1) data)

    /// Similar to the Line chart type, but uses vertical and
    /// horizontal lines to connect the data points in a series
    /// forming a step-like progression.
    static member StepLine<'TY when 'TY :> IConvertible>(data: seq<'TY>) = 
        GenericChart<_>.Create<StepLineChart>(oneY data)
    /// Similar to the Line chart type, but uses vertical and
    /// horizontal lines to connect the data points in a series
    /// forming a step-like progression.
    static member StepLine<'TX, 'TY when 'TX :> IConvertible and 'TY :> IConvertible>(data:seq<'TX * ('TY)>) = 
        GenericChart<_>.Create<StepLineChart>(oneXYSeq data)
    /// Similar to the Line chart type, but uses vertical and
    /// horizontal lines to connect the data points in a series
    /// forming a step-like progression.
    static member StepLine<'TX, 'TY when 'TX :> IConvertible and 'TY :> IConvertible>(xvalues:seq<'TX>, yvalues: seq<'TY>) = 
        GenericChart<_>.Create<StepLineChart>(oneXY xvalues yvalues)
    /// Similar to the Line chart type, but uses vertical and
    /// horizontal lines to connect the data points in a series
    /// forming a step-like progression.
    static member StepLine<'TY when 'TY :> IConvertible>(data:IObservable<'TY>, ?MaxPoints) = 
        GenericChart<_>.Create<StepLineChart>(oneYObs (defaultArg MaxPoints -1) data)
    /// Similar to the Line chart type, but uses vertical and
    /// horizontal lines to connect the data points in a series
    /// forming a step-like progression.
    static member StepLine<'TX, 'TY when 'TY :> IConvertible and 'TX :> IConvertible>(data:IObservable<'TX * ('TY)>, ?MaxPoints) = 
        GenericChart<_>.Create<StepLineChart>(oneXYObs (defaultArg MaxPoints -1) data)

    /// Displays significant stock price points including the open, close, high,
    /// and low price points.
    static member Stock<'TY1, 'TY2, 'TY3, 'TY4 when 'TY1 :> IConvertible and 'TY2 :> IConvertible and 'TY3 :> IConvertible and 'TY4 :> IConvertible>(data: seq<'TY1 * 'TY2 * 'TY3 * 'TY4>) = 
        GenericChart<_>.Create<StockChart>(fourY data)
    /// Displays significant stock price points including the open, close, high,
    /// and low price points.
    static member Stock<'TX, 'TY1, 'TY2, 'TY3, 'TY4 when 'TX :> IConvertible and 'TY1 :> IConvertible and 'TY2 :> IConvertible and 'TY3 :> IConvertible and 'TY4 :> IConvertible>(data:seq<'TX * ('TY1 * 'TY2 * 'TY3 * 'TY4)>) = 
        GenericChart<_>.Create<StockChart>(fourXYSeq data)
    /// Displays significant stock price points including the open, close, high,
    /// and low price points.
    static member Stock<'TX, 'TY1Values, 'TY1, 'TY2Values, 'TY2, 'TY3Values, 'TY3, 'TY4Values, 'TY4 when 'TX :> IConvertible and 'TY1 :> IConvertible and 'TY1Values :> seq<'TY1> and 'TY2 :> IConvertible and 'TY2Values :> seq<'TY2> and 'TY3 :> IConvertible and 'TY3Values :> seq<'TY3> and 'TY4 :> IConvertible and 'TY4Values :> seq<'TY4>>(xvalues:seq<'TX>, yvalues1:'TY1Values, yvalues2:'TY2Values, yvalues3:'TY3Values, yvalues4:'TY4Values) = 
        GenericChart<_>.Create<StockChart>(fourXY xvalues yvalues1 yvalues2 yvalues3 yvalues4)
    /// Displays significant stock price points including the open, close, high,
    /// and low price points.
    static member Stock<'TY1, 'TY2, 'TY3, 'TY4 when 'TY1 :> IConvertible and 'TY2 :> IConvertible and 'TY3 :> IConvertible and 'TY4 :> IConvertible>(data:IObservable<'TY1 * 'TY2 * 'TY3 * 'TY4>, ?MaxPoints) = 
        GenericChart<_>.Create<StockChart>(fourYObs (defaultArg MaxPoints -1) data)
    /// Displays significant stock price points including the open, close, high,
    /// and low price points.
    static member Stock<'TX, 'TY1, 'TY2, 'TY3, 'TY4 when 'TY1 :> IConvertible and 'TY2 :> IConvertible and 'TY3 :> IConvertible and 'TY4 :> IConvertible and 'TX :> IConvertible>(data:IObservable<'TX * ('TY1 * 'TY2 * 'TY3 * 'TY4)>, ?MaxPoints) = 
        GenericChart<_>.Create<StockChart>(fourXYObs (defaultArg MaxPoints -1) data)

    /// Displays a series of vertical boxes, or lines, that reflect
    /// changes in price values.
    static member ThreeLineBreak<'TY when 'TY :> IConvertible>(data: seq<'TY>) = 
        GenericChart<_>.Create<ThreeLineBreakChart>(oneY data)
    /// Displays a series of vertical boxes, or lines, that reflect
    /// changes in price values.
    static member ThreeLineBreak<'TX, 'TY when 'TX :> IConvertible and 'TY :> IConvertible>(data:seq<'TX * ('TY)>) = 
        GenericChart<_>.Create<ThreeLineBreakChart>(oneXYSeq data)
    /// Displays a series of vertical boxes, or lines, that reflect
    /// changes in price values.
    static member ThreeLineBreak<'TX, 'TY when 'TX :> IConvertible and 'TY :> IConvertible>(xvalues:seq<'TX>, yvalues: seq<'TY>) = 
        GenericChart<_>.Create<ThreeLineBreakChart>(oneXY xvalues yvalues)
    /// Displays a series of vertical boxes, or lines, that reflect
    /// changes in price values.
    static member ThreeLineBreak<'TY when 'TY :> IConvertible>(data:IObservable<'TY>, ?MaxPoints) = 
        GenericChart<_>.Create<ThreeLineBreakChart>(oneYObs (defaultArg MaxPoints -1) data)
    /// Displays a series of vertical boxes, or lines, that reflect
    /// changes in price values.
    static member ThreeLineBreak<'TX, 'TY when 'TY :> IConvertible and 'TX :> IConvertible>(data:IObservable<'TX * ('TY)>, ?MaxPoints) = 
        GenericChart<_>.Create<ThreeLineBreakChart>(oneXYObs (defaultArg MaxPoints -1) data)


// [/AUTOGENERATED]

// --------------------------------------------------------------------------------------
// Inclusions for multiple series for Stacked charts
// --------------------------------------------------------------------------------------

    /// Displays series of the same chart type as stacked bars.
    static member StackedBar<'TY when 'TY :> IConvertible>(data: list<list<'TY>>) = 
        GenericChart<_>.Create<StackedBarChart>(seqY data)
    /// Displays series of the same chart type as stacked bars.
    static member StackedBar<'TX, 'TY when 'TX :> IConvertible and 'TY :> IConvertible>(data: list<list<'TX * 'TY>>) = 
        GenericChart<_>.Create<StackedBarChart>(seqXY data)
    /// Displays series of the same chart type as stacked bars.
    static member StackedBar100<'TY when 'TY :> IConvertible>(data: list<list<'TY>>) = 
        GenericChart<_>.Create<StackedBar100Chart>(seqY data)
    /// Displays series of the same chart type as stacked bars.
    static member StackedBar100<'TX, 'TY when 'TX :> IConvertible and 'TY :> IConvertible>(data: list<list<'TX * 'TY>>) = 
        GenericChart<_>.Create<StackedBar100Chart>(seqXY data)

    /// Displays series of the same chart type as stacked columns.
    static member StackedColumn<'TY when 'TY :> IConvertible>(data: list<list<'TY>>) = 
        GenericChart<_>.Create<StackedColumnChart>(seqY data)
    /// Displays series of the same chart type as stacked columns.
    static member StackedColumn<'TX, 'TY when 'TX :> IConvertible and 'TY :> IConvertible>(data: list<list<'TX * 'TY>>) = 
        GenericChart<_>.Create<StackedColumnChart>(seqXY data)
    /// Displays series of the same chart type as stacked columns.
    static member StackedColumn100<'TY when 'TY :> IConvertible>(data: list<list<'TY>>) = 
        GenericChart<_>.Create<StackedColumn100Chart>(seqY data)
    /// Displays series of the same chart type as stacked columns.
    static member StackedColumn100<'TX, 'TY when 'TX :> IConvertible and 'TY :> IConvertible>(data: list<list<'TX * 'TY>>) = 
        GenericChart<_>.Create<StackedColumn100Chart>(seqXY data)

    /// Displays series of the same chart type as stacked areas.
    static member StackedArea<'TY when 'TY :> IConvertible>(data: list<list<'TY>>) = 
        GenericChart<_>.Create<StackedAreaChart>(seqY data)
    /// Displays series of the same chart type as stacked areas.
    static member StackedArea<'TX, 'TY when 'TX :> IConvertible and 'TY :> IConvertible>(data: list<list<'TX * 'TY>>) = 
        GenericChart<_>.Create<StackedAreaChart>(seqXY data)
    /// Displays series of the same chart type as stacked areas.
    static member StackedArea100<'TY when 'TY :> IConvertible>(data: list<list<'TY>>) = 
        GenericChart<_>.Create<StackedArea100Chart>(seqY data)
    /// Displays series of the same chart type as stacked areas.
    static member StackedArea100<'TX, 'TY when 'TX :> IConvertible and 'TY :> IConvertible>(data: list<list<'TX * 'TY>>) = 
        GenericChart<_>.Create<StackedArea100Chart>(seqXY data)

// --------------------------------------------------------------------------------------
// Inclusion for Rows, Columns and Combine charts
// --------------------------------------------------------------------------------------

    static member Rows charts = 
      SubplotChart(charts, Orientation.Vertical)

    static member Columns charts = 
      SubplotChart(charts, Orientation.Horizontal)

    static member Combine charts = 
      CombinedChart charts

// ----------------------------------- 
// Charting.ChartExtensions.fs
// ----------------------------------- 
open ChartData
open ChartTypes

[<AutoOpen>]
module ChartExtensions = 

    type ChartForm<'TData when 'TData :> DataSource and 'TData : (new : unit -> 'TData)>(ch:GenericChart<'TData>) = 
        inherit Form()

        let ctrl = new ChartControl(ch, Dock = DockStyle.Fill)
        do base.Controls.Add(ctrl)

        member x.ChartControl = ctrl
    
    type ChartFormUtilities() =

        static let createCounter() = 
            let count = ref 0
            (fun () -> incr count; !count)

        static let dict = new Dictionary<string, unit -> int>()

        static member ProvideTitle (chart:GenericChart) = 
            let defaultName = 
                match String.IsNullOrEmpty(chart.Name) with
                    | true ->
                        let chartType = 
                            match int chart.ChartType with
                            | -1 -> "Combined"
                            | _ -> chart.ChartType.ToString()
                        chartType  + " Chart"
                    | false -> chart.Name

            match dict.ContainsKey(defaultName) with
                | true ->
                    sprintf "%s (%i)" defaultName (dict.[defaultName]())
                | false ->
                    dict.Add(defaultName, createCounter())
                    defaultName

    type FSharpChart with

        static member Create<'TData when 'TData :> DataSource and 'TData : (new : unit -> 'TData)>(ch:GenericChart<'TData>) =
            let ds = new 'TData()
            let frm = new ChartForm<'TData>(ch, Visible = true, TopMost = true, Width = 700, Height = 500)
            frm.Text <- ChartFormUtilities.ProvideTitle ch
            ds.BindSeries(frm.ChartControl.ChartSeries)
            ds

        static member WithCreate<'TData when 'TData :> DataSource and 'TData : (new : unit -> 'TData)>(ch:GenericChart<'TData>) =
            FSharpChart.Create ch |> ignore
            ch

        static member CopyToClipboard (chart:GenericChart) =
            chart.CopyChartToClipboard()

        static member CopyToClipboardEmf (chart:GenericChart) =
            chart.CopyChartToClipboardEmf(chart.Chart)

        static member SaveAs (filename : string) (format : ChartImageFormat) (chart : GenericChart) =             
            chart.SaveChartAs(filename, format)

// ----------------------------------- 
// Charting.ChartStyleExtensions.fs
// ----------------------------------- 
open ChartFormUtilities
open ChartStyles
open ChartTypes

[<AutoOpen>]
module ChartStyleExtensions = 

    type AreaProperties() = 
        member area.AxisX<'T when 'T :> GenericChart>
          ( ?Enabled, ?LabelStyle, ?IsMarginVisible, ?Maximum, ?Minimum, ?MajorGrid, ?MinorGrid, ?MajorTickMark, ?MinorTickMark, ?Name,
            ?Title, ?TitleAlignment, ?TitleFont, ?TitleForeColor, ?ToolTip) = 
          fun (ch:'T) -> 
            //ch.Area.AxisX <- new Axis(null, AxisName.X)
            Enabled |> Option.iter ch.Area.AxisX.set_Enabled
            LabelStyle |> Option.iter ch.Area.AxisX.set_LabelStyle
            IsMarginVisible |> Option.iter ch.Area.AxisX.set_IsMarginVisible
            Maximum |> Option.iter ch.Area.AxisX.set_Maximum
            Minimum |> Option.iter ch.Area.AxisX.set_Minimum
            MajorGrid |> Option.iter ch.Area.AxisX.set_MajorGrid
            MinorGrid |> Option.iter ch.Area.AxisX.set_MinorGrid
            MajorTickMark |> Option.iter ch.Area.AxisX.set_MajorTickMark
            MinorTickMark |> Option.iter ch.Area.AxisX.set_MinorTickMark
            Name |> Option.iter ch.Area.AxisX.set_Name
            Title |> Option.iter ch.Area.AxisX.set_Title
            TitleAlignment |> Option.iter ch.Area.AxisX.set_TitleAlignment
            TitleFont |> Option.iter ch.Area.AxisX.set_TitleFont
            TitleForeColor |> Option.iter ch.Area.AxisX.set_TitleForeColor
            ToolTip |> Option.iter ch.Area.AxisX.set_ToolTip
            ch

        member area.AxisY<'T when 'T :> GenericChart>
          ( ?Enabled, ?LabelStyle, ?IsMarginVisible, ?Maximum, ?Minimum, ?MajorGrid, ?MinorGrid, ?MajorTickMark, ?MinorTickMark, ?Name,
            ?Title, ?TitleAlignment, ?TitleFont, ?TitleForeColor, ?ToolTip) =
          fun (ch:'T) -> 
            //ch.Area.AxisY <- new Axis(null, AxisName.Y)
            Enabled |> Option.iter ch.Area.AxisY.set_Enabled
            LabelStyle |> Option.iter ch.Area.AxisY.set_LabelStyle
            IsMarginVisible |> Option.iter ch.Area.AxisY.set_IsMarginVisible
            Maximum |> Option.iter ch.Area.AxisY.set_Maximum
            Minimum |> Option.iter ch.Area.AxisY.set_Minimum
            MajorGrid |> Option.iter ch.Area.AxisY.set_MajorGrid
            MinorGrid |> Option.iter ch.Area.AxisY.set_MinorGrid
            MajorTickMark |> Option.iter ch.Area.AxisY.set_MajorTickMark
            MinorTickMark |> Option.iter ch.Area.AxisY.set_MinorTickMark
            Name |> Option.iter ch.Area.AxisY.set_Name
            Title |> Option.iter ch.Area.AxisY.set_Title
            TitleAlignment |> Option.iter ch.Area.AxisY.set_TitleAlignment
            TitleFont |> Option.iter ch.Area.AxisY.set_TitleFont
            TitleForeColor |> Option.iter ch.Area.AxisY.set_TitleForeColor
            ToolTip |> Option.iter ch.Area.AxisY.set_ToolTip
            ch

        member area.AxisX2<'T when 'T :> GenericChart>
          ( ?Enabled, ?LabelStyle, ?IsMarginVisible, ?Maximum, ?Minimum, ?MajorGrid, ?MinorGrid, ?MajorTickMark, ?MinorTickMark, ?Name,
            ?Title, ?TitleAlignment, ?TitleFont, ?TitleForeColor, ?ToolTip) =
          fun (ch:'T) -> 
            //ch.Area.AxisX <- new Axis(null, AxisName.X)
            Enabled |> Option.iter ch.Area.AxisX2.set_Enabled
            LabelStyle |> Option.iter ch.Area.AxisX2.set_LabelStyle
            IsMarginVisible |> Option.iter ch.Area.AxisX2.set_IsMarginVisible
            Maximum |> Option.iter ch.Area.AxisX2.set_Maximum
            Minimum |> Option.iter ch.Area.AxisX2.set_Minimum
            MajorGrid |> Option.iter ch.Area.AxisX2.set_MajorGrid
            MinorGrid |> Option.iter ch.Area.AxisX2.set_MinorGrid
            MajorTickMark |> Option.iter ch.Area.AxisX2.set_MajorTickMark
            MinorTickMark |> Option.iter ch.Area.AxisX2.set_MinorTickMark
            Name |> Option.iter ch.Area.AxisX2.set_Name
            Title |> Option.iter ch.Area.AxisX2.set_Title
            TitleAlignment |> Option.iter ch.Area.AxisX2.set_TitleAlignment
            TitleFont |> Option.iter ch.Area.AxisX2.set_TitleFont
            TitleForeColor |> Option.iter ch.Area.AxisX2.set_TitleForeColor
            ToolTip |> Option.iter ch.Area.AxisX2.set_ToolTip
            ch

        member area.AxisY2<'T when 'T :> GenericChart>
          ( ?Enabled, ?LabelStyle, ?IsMarginVisible, ?Maximum, ?Minimum, ?MajorGrid, ?MinorGrid, ?MajorTickMark, ?MinorTickMark, ?Name,
            ?Title, ?TitleAlignment, ?TitleFont, ?TitleForeColor, ?ToolTip) =
          fun (ch:'T) -> 
            //ch.Area.AxisY <- new Axis(null, AxisName.Y)
            Enabled |> Option.iter ch.Area.AxisY2.set_Enabled
            LabelStyle |> Option.iter ch.Area.AxisY2.set_LabelStyle
            IsMarginVisible |> Option.iter ch.Area.AxisY2.set_IsMarginVisible
            Maximum |> Option.iter ch.Area.AxisY2.set_Maximum
            Minimum |> Option.iter ch.Area.AxisY2.set_Minimum
            MajorGrid |> Option.iter ch.Area.AxisY2.set_MajorGrid
            MinorGrid |> Option.iter ch.Area.AxisY2.set_MinorGrid
            MajorTickMark |> Option.iter ch.Area.AxisY2.set_MajorTickMark
            MinorTickMark |> Option.iter ch.Area.AxisY2.set_MinorTickMark
            Name |> Option.iter ch.Area.AxisY2.set_Name
            Title |> Option.iter ch.Area.AxisY2.set_Title
            TitleAlignment |> Option.iter ch.Area.AxisY2.set_TitleAlignment
            TitleFont |> Option.iter ch.Area.AxisY2.set_TitleFont
            TitleForeColor |> Option.iter ch.Area.AxisY2.set_TitleForeColor
            ToolTip |> Option.iter ch.Area.AxisY2.set_ToolTip
            ch

        member area.Style<'T when 'T :> GenericChart> (?Background) =
          fun (ch:'T) -> 
            Background |> Option.iter (applyBackground ch.Area)
            ch

        member area.Name<'T when 'T :> GenericChart> (?Name) =
          fun (ch:'T) -> 
            Name |> Option.iter ch.Area.set_Name
            ch

        member area.Align<'T when 'T :> GenericChart> (?Area, ?Orientation, ?Style) =
          fun (ch:'T) -> 
            Area |> Option.iter ch.Area.set_AlignWithChartArea
            Style |> Option.iter ch.Area.set_AlignmentStyle
            Orientation |> Option.iter ch.Area.set_AlignmentOrientation
            ch

        member area.Area3DStyle<'T when 'T :> GenericChart> (?Enable3D, ?Inclination, ?IsClustered, ?IsRightAngleAxes, ?LightStyle, ?Perspective, ?PointDepth, ?PointGapDepth, ?Rotation, ?WallWidth) =
          fun (ch:'T) ->
            Enable3D |> Option.iter ch.Area.Area3DStyle.set_Enable3D
            Inclination |> Option.iter ch.Area.Area3DStyle.set_Inclination
            IsClustered |> Option.iter ch.Area.Area3DStyle.set_IsClustered
            IsRightAngleAxes |> Option.iter ch.Area.Area3DStyle.set_IsRightAngleAxes
            LightStyle |> Option.iter ch.Area.Area3DStyle.set_LightStyle
            Perspective |> Option.iter ch.Area.Area3DStyle.set_Perspective
            PointDepth |> Option.iter ch.Area.Area3DStyle.set_PointDepth
            PointGapDepth |> Option.iter ch.Area.Area3DStyle.set_PointGapDepth
            Rotation |> Option.iter ch.Area.Area3DStyle.set_Rotation
            WallWidth |> Option.iter ch.Area.Area3DStyle.set_WallWidth
            ch


    type SeriesProperties() = 
  
          member series.AxisType<'T when 'T :> GenericChart> (?YAxisType, ?XAxisType) =
            fun (ch:'T) -> 
              YAxisType |> Option.iter ch.Series.set_YAxisType
              XAxisType |> Option.iter ch.Series.set_XAxisType
              ch
  
          member series.Style<'T when 'T :> GenericChart> (?Color, ?BorderColor, ?BorderWidth) =
            fun (ch:'T) -> 
              Color |> Option.iter ch.Series.set_Color
              BorderColor |> Option.iter ch.Series.set_BorderColor
              BorderWidth |> Option.iter ch.Series.set_BorderWidth
              ch

          member series.DataPoint<'T when 'T :> GenericChart> (?Label, ?LabelToolTip, ?ToolTip) =
            fun (ch:'T) ->               
              Label |> Option.iter ch.Series.set_Label
              LabelToolTip |> Option.iter ch.Series.set_LabelToolTip
              ToolTip |> Option.iter ch.Series.set_ToolTip
              ch

          member series.Marker<'T when 'T :> GenericChart> (?Color, ?Size, ?Step, ?Style, ?BorderColor, ?BorderWidth) =
            fun (ch:'T) -> 
              BorderColor |> Option.iter ch.Series.set_MarkerBorderColor
              BorderWidth |> Option.iter ch.Series.set_MarkerBorderWidth
              Color |> Option.iter ch.Series.set_MarkerColor
              Size |> Option.iter ch.Series.set_MarkerSize
              Step |> Option.iter ch.Series.set_MarkerStep
              Style |> Option.iter ch.Series.set_MarkerStyle
              ch

    type FSharpChart with 
        static member WithArea = AreaProperties()
        static member WithSeries = SeriesProperties()

        static member WithLegend<'T when 'T :> GenericChart>
            ( ?Title, ?Background, ?Font, ?Alignment, ?Docking, ?InsideArea,
              ?TitleAlignment, ?TitleFont, ?TitleForeColor, ?BorderColor, ?BorderWidth, ?BorderDashStyle) =
          fun (ch:'T) -> 
            let legend = new Legend()
            applyPropertyDefaults (ch.ChartType) legend
            InsideArea |> Option.iter legend.set_IsDockedInsideChartArea
            Background |> Option.iter (applyBackground legend)
            Font |> Option.iter legend.set_Font
            Alignment |> Option.iter legend.set_Alignment
            Docking |> Option.iter legend.set_Docking
            Title |> Option.iter legend.set_Title
            TitleAlignment |> Option.iter legend.set_TitleAlignment
            TitleFont |> Option.iter legend.set_TitleFont
            TitleForeColor |> Option.iter legend.set_TitleForeColor
            BorderColor |> Option.iter legend.set_BorderColor
            BorderDashStyle |> Option.iter legend.set_BorderDashStyle
            BorderWidth |> Option.iter legend.set_BorderWidth
            ch.Legends.Add legend
            ch
      
        static member WithMargin<'T when 'T :> GenericChart> (left, top, right, bottom) =
          fun (ch:'T) ->
            ch.Margin <- (left, top, right, bottom)
            ch

        static member WithStyle<'T when 'T :> GenericChart> (?Background) =
          fun (ch:'T) -> 
            Background |> Option.iter (applyBackground ch.Chart)
            ch

        static member WithTitle<'T when 'T :> GenericChart>
            ( ?Text, ?TextStyle, ?Font, ?Background, ?Color, ?BorderColor, ?BorderWidth, ?BorderDashStyle, 
              ?TextOrientation, ?Alignment, ?Docking, ?InsideArea) =
          fun (ch:'T) ->
              let title = new Title()
              applyPropertyDefaults (ch.ChartType) title
              Text |> Option.iter title.set_Text 
              Color |> Option.iter title.set_ForeColor
              BorderColor |> Option.iter title.set_BorderColor
              BorderDashStyle |> Option.iter title.set_BorderDashStyle
              BorderWidth |> Option.iter title.set_BorderWidth
              TextStyle |> Option.iter title.set_TextStyle
              TextOrientation |> Option.iter title.set_TextOrientation
              InsideArea |> Option.iter title.set_IsDockedInsideChartArea
              Background |> Option.iter (applyBackground title)
              Font |> Option.iter title.set_Font
              Alignment |> Option.iter title.set_Alignment
              Docking |> Option.iter title.set_Docking
              ch.Titles.Add title
              ch

    type StyleHelper =

        static member private FontCreate(fName:string option, fFamily:FontFamily option, fStyle:FontStyle option, fSize:float32 option) =
            let fontSize = 
                match fSize with
                | Some(size) -> size
                | None -> DefaultFont.Size
            let fontStyle = 
                match fStyle with
                | Some(style) -> style
                | None -> DefaultFont.Style
            let font =
                match (fFamily, fName) with
                | (Some(family), _) -> new Font(family, fontSize, fontStyle)
                | (_, Some(name)) -> new Font(name, fontSize, fontStyle)
                | (None, None) -> new Font(DefaultFont.FontFamily, fontSize, fontStyle)
            font

        static member LabelStyle
            ( ?Angle, ?Color, ?Format, ?Interval, ?IntervalOffset, ?IntervalOffsetType, ?IntervalType, ?IsEndLabelVisible, ?IsStaggered, ?TruncatedLabels,
              ?FontName:string, ?FontFamily:FontFamily, ?FontStyle:FontStyle, ?FontSize:float32) =
              let labelStyle = new System.Windows.Forms.DataVisualization.Charting.LabelStyle()
              Angle |> Option.iter labelStyle.set_Angle
              Color |> Option.iter labelStyle.set_ForeColor
              Format |> Option.iter labelStyle.set_Format
              Interval |> Option.iter labelStyle.set_Interval
              IntervalOffset |> Option.iter labelStyle.set_IntervalOffset
              IntervalOffsetType |> Option.iter labelStyle.set_IntervalOffsetType
              IntervalType |> Option.iter labelStyle.set_IntervalType
              IsStaggered |> Option.iter labelStyle.set_IsStaggered
              TruncatedLabels |> Option.iter labelStyle.set_TruncatedLabels
              if FontName.IsSome || FontFamily.IsSome || FontStyle.IsSome || FontSize.IsSome then
                 labelStyle.set_Font (StyleHelper.FontCreate(FontName, FontFamily, FontStyle, FontSize))
              labelStyle

        static member Legend
            ( ?Title, ?Background, ?Alignment, ?Docking, ?InsideArea,
              ?BorderColor, ?BorderWidth, ?BorderDashStyle, 
              ?FontName:string, ?FontFamily:FontFamily, ?FontStyle:FontStyle, ?FontSize:float32) =
              let legend = new Legend()
              InsideArea |> Option.iter legend.set_IsDockedInsideChartArea
              Background |> Option.iter (applyBackground legend)
              Alignment |> Option.iter legend.set_Alignment
              Docking |> Option.iter legend.set_Docking
              Title |> Option.iter legend.set_Title
              BorderColor |> Option.iter legend.set_BorderColor
              BorderDashStyle |> Option.iter legend.set_BorderDashStyle
              BorderWidth |> Option.iter legend.set_BorderWidth
              if FontName.IsSome || FontFamily.IsSome || FontStyle.IsSome || FontSize.IsSome then
                  legend.set_Font (StyleHelper.FontCreate(FontName, FontFamily, FontStyle, FontSize))
              legend

        static member Title
            ( ?Text, ?TextStyle, ?Background, ?Color, ?BorderColor, ?BorderWidth, ?BorderDashStyle, 
              ?TextOrientation, ?Alignment, ?Docking, ?InsideArea,
              ?FontName:string, ?FontFamily:FontFamily, ?FontStyle:FontStyle, ?FontSize:float32) =
              let title = new Title()
              Text |> Option.iter title.set_Text 
              Color |> Option.iter title.set_ForeColor
              BorderColor |> Option.iter title.set_BorderColor
              BorderDashStyle |> Option.iter title.set_BorderDashStyle
              BorderWidth |> Option.iter title.set_BorderWidth
              TextStyle |> Option.iter title.set_TextStyle
              TextOrientation |> Option.iter title.set_TextOrientation
              InsideArea |> Option.iter title.set_IsDockedInsideChartArea
              Background |> Option.iter (applyBackground title)
              Alignment |> Option.iter title.set_Alignment
              Docking |> Option.iter title.set_Docking
              if FontName.IsSome || FontFamily.IsSome || FontStyle.IsSome || FontSize.IsSome then
                  title.set_Font (StyleHelper.FontCreate(FontName, FontFamily, FontStyle, FontSize))
              title

        static member Font(?FamilyName:string, ?FontFamily:FontFamily, ?FontStyle:FontStyle, ?FontSize:float32) =
            StyleHelper.FontCreate(FamilyName, FontFamily, FontStyle, FontSize)



#if INTERACTIVE
module InstallFsiAutoDisplay =
  fsi.AddPrinter(fun (ch:GenericChart) -> 
    let frm = new Form(Visible = true, TopMost = true, Width = 700, Height = 500)
    let ctl = new ChartControl(ch, Dock = DockStyle.Fill)
    frm.Text <- ChartFormUtilities.ProvideTitle ch
    frm.Controls.Add(ctl)
    frm.Show()
    ctl.Focus() |> ignore
    "(Chart)")
#endif
